This is an R Markdown Notebook for analysis using data on the DC Bus System (WMATA Metrobus). The data were obtained here:

https://planitmetro.com/2016/11/16/data-download-metrobus-vehicle-location-data/

Control + Alt + Shift + m = rename in scope

Load the packages to be used.

package ‘tidyr’ was built under R version 3.2.5package ‘plyr’ was built under R version 3.2.5package ‘stringr’ was built under R version 3.2.5package ‘geosphere’ was built under R version 3.2.5

Get the Bus data.

First let’s check the working directory.

getwd()
[1] "/Users/mdturse/Desktop/Analytics/DCMetroBus"

Then, actually get the data.

The working directory was changed to /Users/mdturse/Desktop/Analytics/DCMetroBus/Bus AVL Oct 2016 inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the the working directory for notebook chunks.Oct03Raw
'data.frame':   620274 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 11 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : Factor w/ 10552 levels "","1000001","1000003",..: 9682 9682 9683 9641 9640 8136 9668 9668 9796 9795 ...
 $ Stop_Desc        : Factor w/ 7740 levels "10TH ST + MICHIGAN AVE",..: 1346 1346 7417 7418 1346 2940 2939 2939 6926 6929 ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : Factor w/ 75354 levels "10-3-16 1:00:00 AM",..: 47380 47506 47740 47814 47864 48244 48302 48540 49086 49190 ...
 $ Departure_Time   : Factor w/ 75396 levels "10-3-16 1:00:00 AM",..: 47406 47554 47766 47840 47890 48270 48536 48566 49112 49216 ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
Oct04Raw
'data.frame':   623427 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 225 225 225 225 225 225 225 225 225 225 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 6 6 6 6 6 6 6 ...
 $ Route_Direction  : Factor w/ 9 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 8 1 1 1 1 3 2 5 ...
 $ Stop_ID          : Factor w/ 10555 levels "","1000001","1000003",..: 9671 9671 8138 8138 8138 8138 8138 9798 9799 9638 ...
 $ Stop_Desc        : Factor w/ 7717 levels "10TH ST + MICHIGAN AVE",..: 2939 2939 2940 2940 2940 2940 2940 6906 6903 4205 ...
 $ Event_Type       : int  3 4 3 3 3 5 5 4 5 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 3 1 1 1 2 2 3 2 3 ...
 $ Event_Time       : Factor w/ 77713 levels "10-4-16 1:00:00 AM",..: 49126 49240 50858 50908 50976 51116 51172 51714 51842 51940 ...
 $ Departure_Time   : Factor w/ 77739 levels "10-4-16 1:00:00 AM",..: 49209 49251 50869 50957 50987 51165 51185 51725 51933 51951 ...
 $ Dwell_Time       : int  79 0 59 19 59 19 1 0 40 0 ...
 $ Delta_Time       : int  35 36 36 246 244 255 264 159 129 139 ...
 $ Odometer_Distance: int  56958 60750 69747 69971 69747 71136 71177 76520 77425 78353 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  58 89 82 76 79 301 274 104 310 2 ...
Oct05Raw
'data.frame':   630900 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Route_Direction  : Factor w/ 11 levels "ANTICLKW","CLOCKWIS",..: 5 5 5 5 5 5 5 5 5 5 ...
 $ Stop_Sequence    : int  1 1 3 4 5 4 3 3 7 7 ...
 $ Stop_ID          : Factor w/ 10543 levels "","1000001","1000003",..: 9659 9659 9632 9633 9624 9633 9632 9632 9673 9673 ...
 $ Stop_Desc        : Factor w/ 7725 levels "10TH ST + MICHIGAN AVE",..: 2946 2946 7403 7401 7401 7401 7403 7403 1346 1346 ...
 $ Event_Type       : int  3 5 4 4 3 4 3 3 5 5 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 2 3 3 1 3 1 1 2 2 ...
 $ Event_Time       : Factor w/ 77725 levels "10-5-16 1:00:00 AM",..: 49279 49371 49899 49953 49993 50135 50221 50493 50783 50987 ...
 $ Departure_Time   : Factor w/ 77716 levels "10-5-16 1:00:00 AM",..: 49257 49353 49877 49931 49997 50113 50421 50489 50767 50999 ...
 $ Dwell_Time       : int  189 2 0 0 13 0 111 9 3 17 ...
 $ Delta_Time       : int  4 78 -114 -3 19 93 297 191 382 499 ...
 $ Odometer_Distance: int  37932 38703 44242 44327 44645 45927 46733 47077 50461 51916 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  316 104 276 246 229 246 345 207 109 305 ...
Oct06Raw
'data.frame':   621948 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 265 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Route_Direction  : Factor w/ 9 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 7 6 5 4 3 7 7 7 ...
 $ Stop_ID          : Factor w/ 10562 levels "","1000001","1000003",..: 9678 9678 9692 9693 9643 9652 9651 9692 9692 9692 ...
 $ Stop_Desc        : Factor w/ 7723 levels "10TH ST + MICHIGAN AVE",..: 2937 2937 1342 7400 7399 7399 7401 1342 1342 1342 ...
 $ Event_Type       : int  3 5 4 5 3 4 3 4 5 5 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 2 3 2 1 3 1 3 2 2 ...
 $ Event_Time       : Factor w/ 77758 levels "10-6-16 1:00:00 AM",..: 49294 49384 49982 49998 50058 50186 50270 50518 51002 51064 ...
 $ Departure_Time   : Factor w/ 77792 levels "10-6-16 1:00:00 AM",..: 49305 49399 49993 50023 50091 50197 50487 50529 51065 51079 ...
 $ Dwell_Time       : int  148 2 0 7 11 0 103 0 26 2 ...
 $ Delta_Time       : int  -6 64 -87 -93 31 104 303 175 497 504 ...
 $ Odometer_Distance: int  37950 38726 44130 44197 44592 45935 46739 51826 51826 51838 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  284 71 199 164 223 246 343 199 306 320 ...
Oct07Raw
'data.frame':   622894 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 6 6 6 6 6 6 7 7 ...
 $ Route_Direction  : Factor w/ 7 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 2 3 3 5 6 7 1 2 ...
 $ Stop_ID          : Factor w/ 10556 levels "","1000001","1000003",..: 9672 9672 9800 9799 9799 9639 9640 9641 9641 9642 ...
 $ Stop_Desc        : Factor w/ 7699 levels "10TH ST + MICHIGAN AVE",..: 2930 2930 6886 6889 6889 4196 4199 6887 6887 4198 ...
 $ Event_Type       : int  3 4 3 4 5 4 4 3 3 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 3 1 3 2 3 3 1 1 3 ...
 $ Event_Time       : Factor w/ 77562 levels "10-7-16 1:00:00 AM",..: 49134 49136 51718 51756 51888 51934 52018 52044 52130 52288 ...
 $ Departure_Time   : Factor w/ 77649 levels "10-7-16 1:00:00 AM",..: 49193 49195 51779 51815 51953 51993 52077 52103 52189 52347 ...
 $ Dwell_Time       : int  153 0 1 0 3 0 0 120 120 0 ...
 $ Delta_Time       : int  57 56 165 270 197 201 181 189 235 288 ...
 $ Odometer_Distance: int  37846 42154 56018 56611 57411 58341 59084 59787 59787 60252 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  98 89 201 104 26 2 1 247 247 182 ...

Put the daily data together.

AllDays <- bind_rows(list(Oct03Raw, Oct04Raw, Oct05Raw, Oct06Raw, Oct07Raw),
                     .id = c("group")
                    )
Unequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to character
# dim(AllDays)
str(AllDays)
'data.frame':   3119443 obs. of  18 variables:
 $ group            : chr  "1" "1" "1" "1" ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : chr  "LOOP" "LOOP" "LOOP" "LOOP" ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : chr  "10-3-16 6:06:47 AM" "10-3-16 6:07:50 AM" "10-3-16 6:09:47 AM" "10-3-16 6:10:24 AM" ...
 $ Departure_Time   : chr  "10-3-16 6:06:47 AM" "10-3-16 6:08:01 AM" "10-3-16 6:09:47 AM" "10-3-16 6:10:24 AM" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...

Deleting old data frames.

for (i in 3:7){
  rm(list = ls(pattern = paste0("Oct0", i, "Raw")
              )
    )
  
  message("Deleting Oct0", i, "Raw")
  }
Deleting Oct03Raw
Deleting Oct04Raw
Deleting Oct05Raw
Deleting Oct06Raw
Deleting Oct07Raw

Updating variable types.

Then, sorting the data and adding a RowNumber (to be used for identifying rows later in the analyses.)

rm(i)
AllDays$group <- factor(AllDays$group)
AllDays$Route_Direction <- factor(AllDays$Route_Direction)
AllDays$Event_Time <- as.POSIXct(AllDays$Event_Time, format = "%m-%d-%y %I:%M:%S %p")
AllDays$Departure_Time <- as.POSIXct(AllDays$Departure_Time, format = "%m-%d-%y %I:%M:%S %p")
str(AllDays)
'data.frame':   3119443 obs. of  18 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
AllDays_Sorted <- arrange(AllDays,
                          Bus_ID,
                          Event_Time
                         ) %>% 
  mutate(RowNum_OG = row_number() # this is useful in identify the row later on
        )
rm(AllDays)
str(AllDays_Sorted)
'data.frame':   3119443 obs. of  19 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
# View(head(AllDays_Sorted, 100))

Inspecting the values of Stop_ID, and finding that it can take the values “” (blank) and “NULL”.

View(group_by(AllDays_Sorted,
              Stop_ID
             ) %>% 
       summarise(
         Cnt = n()
         ) %>% 
       arrange(Stop_ID)
    )
View(filter(AllDays_Sorted,
            is.na(Stop_ID) |
              Stop_ID == "" |
              Stop_ID == "NULL"
           ) %>% 
       arrange(Stop_Desc)
    )

Creating a table of distinct Stop_Desc values when Stop_ID is “” (blank) or “NULL”.

StopID_New <- filter(AllDays_Sorted,
                     is.na(Stop_ID) |
                       Stop_ID == "" |
                       Stop_ID == "NULL"
                    ) %>% 
  select(Stop_ID, Stop_Desc) %>% 
  distinct() %>% 
  arrange(Stop_ID, Stop_Desc) %>% 
  mutate(StopID_New = 1:nrow(.)
        )
View(StopID_New)

Creating a full updated table by filling in StopID_New for when Stop_ID is “” (blank) or NULL.

AllDays_StopIDNew <- left_join(AllDays_Sorted,
                               select(StopID_New,
                                      Stop_Desc,
                                      StopID_New
                                     ),
                               by = c("Stop_Desc" = "Stop_Desc")
                              ) %>% 
  mutate(StopID_Clean = ifelse(is.na(StopID_New),
                               Stop_ID,
                               StopID_New
                              ),
         StopID_Indicator = factor(ifelse(is.na(StopID_New),
                                          "ID_OK",
                                          "ID_Bad"
                                         )
                                  )
        )
rm(StopID_New)
rm(AllDays_Sorted)
str(AllDays_StopIDNew)
'data.frame':   3119443 obs. of  22 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
# View(tail(AllDays_StopIDNew, 500))
# View(filter(AllDays_StopIDNew,
#             Stop_Desc == "METROWAY ANNNOUCEMNT CORR"
#            )
#     )

Lat Long stats for pulling in Zip codes later.

LL_Stats <- group_by(AllDays_StopIDNew,
                     StopID_Clean
                    ) %>% 
  summarise(Lat_Mean = mean(Latitude, na.rm = TRUE),
            Lat_Med = median(Latitude, na.rm = TRUE),
            Lng_Mean = mean(Longitude, na.rm = TRUE),
            Lng_Med = median(Longitude, na.rm = TRUE)
           ) %>% 
  mutate(Lat_MeaLessMed = Lat_Mean - Lat_Med,
         Lng_MeaLessMed = Lng_Mean - Lng_Med,
         RowNum = row_number()
        )
str(LL_Stats)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   10588 obs. of  8 variables:
 $ StopID_Clean  : chr  "1" "10" "1000001" "1000003" ...
 $ Lat_Mean      : num  38.9 39 38.8 38.8 38.8 ...
 $ Lat_Med       : num  38.9 39 38.8 38.8 38.8 ...
 $ Lng_Mean      : num  -77.1 -77.4 -77 -77 -77 ...
 $ Lng_Med       : num  -77.1 -77.4 -77 -77 -77 ...
 $ Lat_MeaLessMed: num  8.37e-05 0.00 -5.40e-06 2.15e-05 9.27e-06 ...
 $ Lng_MeaLessMed: num  -8.47e-05 0.00 1.07e-05 1.62e-04 -4.82e-07 ...
 $ RowNum        : int  1 2 3 4 5 6 7 8 9 10 ...
summary(LL_Stats)
 StopID_Clean          Lat_Mean        Lat_Med         Lng_Mean     
 Length:10588       Min.   :38.09   Min.   :38.60   Min.   :-77.45  
 Class :character   1st Qu.:38.85   1st Qu.:38.85   1st Qu.:-77.10  
 Mode  :character   Median :38.90   Median :38.90   Median :-77.01  
                    Mean   :38.91   Mean   :38.91   Mean   :-77.03  
                    3rd Qu.:38.96   3rd Qu.:38.96   3rd Qu.:-76.95  
                    Max.   :39.19   Max.   :39.19   Max.   :-75.42  
    Lng_Med       Lat_MeaLessMed       Lng_MeaLessMed           RowNum     
 Min.   :-77.45   Min.   :-0.8069882   Min.   :-0.0102476   Min.   :    1  
 1st Qu.:-77.10   1st Qu.:-0.0000126   1st Qu.:-0.0000167   1st Qu.: 2648  
 Median :-77.01   Median : 0.0000003   Median :-0.0000003   Median : 5294  
 Mean   :-77.03   Mean   :-0.0001867   Mean   : 0.0003654   Mean   : 5294  
 3rd Qu.:-76.95   3rd Qu.: 0.0000141   3rd Qu.: 0.0000148   3rd Qu.: 7941  
 Max.   :-76.67   Max.   : 0.0093569   Max.   : 1.6050662   Max.   :10588  
View(head(arrange(LL_Stats,
                  Lat_MeaLessMed
                 ),
          500
         )
    )
View(head(arrange(LL_Stats,
                  desc(Lat_MeaLessMed)
                 ),
          500
         )
    )
View(head(arrange(LL_Stats,
                  Lng_MeaLessMed
                 ),
          500
         )
    )
View(head(arrange(LL_Stats,
                  desc(Lng_MeaLessMed)
                 ),
          500
         )
    )

Pulling in Zip Code data from api.geonames.org.

LL_StatsZips <- left_join(LL_Stats_UnqLatLng,
                          Zips_All,
                          by = c("UniqueLatLng" = "UniqueLatLng")
                         )
str(LL_StatsZips)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   10588 obs. of  20 variables:
 $ StopID_Clean  : chr  "1" "10" "1000001" "1000003" ...
 $ Lat_Mean      : num  38.9 39 38.8 38.8 38.8 ...
 $ Lat_Med       : num  38.9 39 38.8 38.8 38.8 ...
 $ Lng_Mean      : num  -77.1 -77.4 -77 -77 -77 ...
 $ Lng_Med       : num  -77.1 -77.4 -77 -77 -77 ...
 $ Lat_MeaLessMed: num  8.37e-05 0.00 -5.40e-06 2.15e-05 9.27e-06 ...
 $ Lng_MeaLessMed: num  -8.47e-05 0.00 1.07e-05 1.62e-04 -4.82e-07 ...
 $ RowNum        : int  1 2 3 4 5 6 7 8 9 10 ...
 $ UniqueLatLng  : chr  "38.85738__-77.055138" "38.962704__-77.433685" "38.816044__-77.017685" "38.816292__-77.018036" ...
 $ id            : chr  "1" "1" "1" "1" ...
 $ adminCode2    : chr  "013" "107" "001" "001" ...
 $ adminCode1    : chr  "VA" "VA" "DC" "DC" ...
 $ adminName2    : chr  "Arlington" "Loudoun" "District of Columbia" "District of Columbia" ...
 $ lng           : num  -77.1 -77.4 -77 -77 -77 ...
 $ distance      : chr  "0" "0" "0" "0" ...
 $ countryCode   : chr  "US" "US" "US" "US" ...
 $ postalCode    : chr  "22202" "20166" "20032" "20032" ...
 $ adminName1    : chr  "Virginia" "Virginia" "District of Columbia" "District of Columbia" ...
 $ placeName     : chr  "Arlington" "Sterling" "Washington" "Washington" ...
 $ lat           : num  38.9 39 38.8 38.8 38.8 ...

Join to create one dataset that also includes Zip variables.

rm(AllDays_StopIDNew, LL_StatsZips)
str(AllDays_Zips)
'data.frame':   3119443 obs. of  41 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med          : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean         : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med          : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed   : num  -0.000794 -0.000794 -0.000185 -0.000173 0.000162 ...
 $ Lng_MeaLessMed   : num  3.72e-04 3.72e-04 -6.78e-04 1.69e-04 4.11e-05 ...
 $ RowNum           : int  9715 9715 9716 9674 9673 8168 9701 9701 9829 9828 ...
 $ UniqueLatLng     : chr  "38.767807__-77.155136" "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" ...
 $ id               : chr  "10" "10" "10" "10" ...
 $ adminCode2       : chr  "059" "059" "059" "059" ...
 $ Stop_State       : chr  "VA" "VA" "VA" "VA" ...
 $ Stop_County      : chr  "Fairfax" "Fairfax" "Fairfax" "Fairfax" ...
 $ lng              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance         : chr  "0" "0" "0" "0" ...
 $ countryCode      : chr  "US" "US" "US" "US" ...
 $ Stop_Zip         : chr  "22310" "22310" "22310" "22310" ...
 $ adminName1       : chr  "Virginia" "Virginia" "Virginia" "Virginia" ...
 $ Stop_City        : chr  "Alexandria" "Alexandria" "Alexandria" "Alexandria" ...
 $ lat              : num  38.8 38.8 38.8 38.8 38.8 ...

Updating variable types.

AllDays_Zips$distance <- as.numeric(AllDays_Zips$distance)
AllDays_Zips$countryCode <- factor(AllDays_Zips$countryCode)
AllDays_Zips$adminName1 <- factor(AllDays_Zips$adminName1)
str(AllDays_Zips)
'data.frame':   3119443 obs. of  41 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med          : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean         : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med          : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed   : num  -0.000794 -0.000794 -0.000185 -0.000173 0.000162 ...
 $ Lng_MeaLessMed   : num  3.72e-04 3.72e-04 -6.78e-04 1.69e-04 4.11e-05 ...
 $ RowNum           : int  9715 9715 9716 9674 9673 8168 9701 9701 9829 9828 ...
 $ UniqueLatLng     : chr  "38.767807__-77.155136" "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" ...
 $ id               : chr  "10" "10" "10" "10" ...
 $ adminCode2       : chr  "059" "059" "059" "059" ...
 $ Stop_State       : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County      : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance         : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode      : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip         : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 150 123 123 123 123 123 ...
 $ adminName1       : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City        : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 2 49 49 49 49 49 ...
 $ lat              : num  38.8 38.8 38.8 38.8 38.8 ...

Feature engineering.

Inspecting incidences of consecutive Stop_IDs. This is done because investigation showed that many conseutive events occurr at the same Stop_ID, but with various Dwell_Times, Odometer_Distances, etc. All of which affect calculations and analyses.

Create data on the runs (consecutive Stop_IDs).

StopID_Runs <- rle(AllDays_Zips$StopID_Clean)
StopID_Runs$ends <- cumsum(StopID_Runs$lengths)
StopID_Runs$starts <- ifelse(is.na(lag(StopID_Runs$ends)
                                  ),
                             1,
                             lag(StopID_Runs$ends) + 1
                            )
str(StopID_Runs)
List of 4
 $ lengths: int [1:2809529] 2 1 1 1 1 2 1 1 1 1 ...
 $ values : chr [1:2809529] "5004572" "5004573" "5002210" "5002209" ...
 $ ends   : int [1:2809529] 2 3 4 5 6 8 9 10 11 12 ...
 $ starts : num [1:2809529] 1 3 4 5 6 7 9 10 11 12 ...
 - attr(*, "class")= chr "rle"
# class(StopID_Runs)
# 
# StopID_Runs_df <- data.frame(unclass(StopID_Runs))
# str(StopID_Runs_df)
# class(StopID_Runs_df)
# rm(StopID_Runs_df)

Trying to link data on RunsGroups with the original data (AllDays_Sorted). The goal is to select only one record per RunsGroup - that being the record with the longest Dwell_Time.

I attempted this computation using both data.frames (dplyr) and data.tables (data.table). However, with 2,809,062 rows in one dataset and 3,119,443 rows in the other dataset, the current computation time is over 5 days…so I’m trying a different strategy to only select the first record in a run.

# Create a RunsGroup variable for each run
# StopID_Runs_df$RunsGroup <- paste0("g", seq(1:nrow(StopID_Runs_df)
#                                            )
#                                   )
# 
# str(StopID_Runs_df)
# head(StopID_Runs_df, 25)
# tail(StopID_Runs_df, 25)
# 
# StopID_Runs_df <- StopID_Runs_df %>% 
#   mutate(RowNum = row_number()
#         )
# 
# str(StopID_Runs_df)
# head(StopID_Runs_df, 25)
# tail(StopID_Runs_df, 25)
# 
# 
# # Converting to data.tables for, hopefully, improved performance (speed) in computation
# StopID_Runs_dt <- data.table(StopID_Runs_df)
# setkey(StopID_Runs_dt, RowNum)
# str(StopID_Runs_dt)
# 
# AllDays_Sorted_dt <- data.table(AllDays_Sorted)
# setkey(AllDays_Sorted_dt, RowNum_OG)
# str(AllDays_Sorted_dt)
# # rm(AllDays_Sorted_dt)
# 
# 
# # Actual loop to perform the computations and link to original data (AllDays_Sorted_dt)
# GroupData <- list()
# for(i in 1:nrow(StopID_Runs_dt)
#    ) {
#   assign(paste0("group_", i),
#            StopID_Runs_dt[RowNum == i, RunsGroup]
#           )
# 
#     #####  The code below is the same code as above, but done with dplyr  #####
# 
#     # assign(paste0("group_", i),
#   #        filter(StopID_Runs_df,
#   #               RowNum == i
#   #              ) %>% 
#   #          select(RunsGroup)
#   #       )
# 
#   assign(paste0("group_", i, "_start"),
#          StopID_Runs_dt[RowNum == i, starts]
#         )
# 
#   assign(paste0("group_", i, "_end"),
#          StopID_Runs_dt[RowNum == i, ends]
#         )
# 
#   assign(paste0("group_", i, "_rows"),
#          AllDays_Sorted_dt[RowNum_OG >= as.numeric(get(paste0("group_", i, "_start")
#                                                       )
#                                                   ) &
#                            RowNum_OG <= as.numeric(get(paste0("group_", i, "_end")
#                                                       )
#                                                   ),
#                            RunsGroup := as.character(get(paste0("group_", i)
#                                                         )
#                                                     )
#                           ]
# 
#     #####  The code below is the same as the code above, but done with dplyr  #####
# 
#          # filter(AllDays_Sorted,
#          #        between(RowNum_OG,
#          #                as.numeric(get(paste0("group_", i, "_start")
#          #                              )
#          #                          ),
#          #                as.numeric(get(paste0("group_", i, "_end")
#          #                              )
#          #                          )
#          #               )
#          #       ) %>% 
#          #   mutate(RunsGroup = as.character(get(paste0("group_", i)
#          #                                     )
#          #                                 )
#          #        )
#         )
# 
#   GroupData[[i]] <- get(paste0("group_", i, "_rows"))
# 
#   message("Processing Group ", i, " of 2,809,062")
# }
# 
# 
# GroupData_df <- rbind.fill(GroupData)
# str(GroupData_df)
# head(GroupData_df)
# tail(GroupData_df)
# # rm(GroupData_df)
# 
# 
# group_1
# group_1_start
# group_1_end
# group_1_rows
# group_2_rows
# group_3_rows
# group_50_rows
# str(group_50_rows)
# group_2809062_rows
# GroupData[[1]]
# GroupData[[50]]
# 
# 
# #####  Testing Area (Below)  #####
# #####  Testing Area (Below)  #####
# #####  Testing Area (Below)  #####
# 
# # head(StopID_Runs$starts, 20)
# # head(AllDays_NewOrder$Stop_ID, 20)
# # 
# # 
# # dat <- as.data.frame(c(1,1,7,7,7,9,6,8,2,2,2,1,1,1,1,1))
# # colnames(dat)[1] <- "dat"
# # r <- rle(dat$dat)
# # dat$run <- rep(r$lengths, r$lengths)
# # dat$runLag <- lag(dat$run)
# # dat$cond <- rep(r$values, r$lengths)
# # dat
# # View(dat)

When consecutive Stop_ID occurrs, only take the first occurrence. This is done because the computation time to select only the record with the longest Dwell_Time for each run was too long (over 5 days).

This is probably less than ideal with regards to Dwell_Time, but should not make much difference for calculations of travel time, speed, etc.

AllDays_FirstStopID <- AllDays_Zips[StopID_Runs$starts, ]
dim(AllDays_Zips)
[1] 3119443      41
dim(AllDays_FirstStopID)
[1] 2809529      41
nrow(AllDays_Zips) - nrow(AllDays_FirstStopID)
[1] 309914
rm(AllDays_Zips)
rm(StopID_Runs)
str(AllDays_FirstStopID)
'data.frame':   2809529 obs. of  41 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type       : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time       : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time       : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance: int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG        : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med          : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean         : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med          : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed   : num  -7.94e-04 -1.85e-04 -1.73e-04 1.62e-04 4.75e-05 ...
 $ Lng_MeaLessMed   : num  3.72e-04 -6.78e-04 1.69e-04 4.11e-05 -1.52e-04 ...
 $ RowNum           : int  9715 9716 9674 9673 8168 9701 9829 9828 9667 9829 ...
 $ UniqueLatLng     : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ id               : chr  "10" "10" "10" "10" ...
 $ adminCode2       : chr  "059" "059" "059" "059" ...
 $ Stop_State       : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County      : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance         : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode      : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip         : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ adminName1       : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City        : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ lat              : num  38.8 38.8 38.8 38.8 38.8 ...

Feature engineering.

Creating new variables.

AllDays_AddVars <- mutate(AllDays_FirstStopID,
                          Odometer_Distance_Mi = Odometer_Distance / 5280, #5,280 feet in 1 mile
                          Dwell_Time2 = as.numeric(Departure_Time - Event_Time),
                          Event_Time_Yr = as.integer(year(Event_Time)),
                          Event_Time_Mth = as.integer(month(Event_Time)),
                          Event_Time_Date = day(Event_Time),
                          Event_Time_Day = wday(Event_Time, label = TRUE),
                          Event_Time_Hr = hour(Event_Time),
                          Event_Time_Min = minute(Event_Time),
                          Event_Time_HrGroup = factor(ifelse(Event_Time_Hr < 3,
                                                             "Group0_2",
                                                      ifelse(Event_Time_Hr < 6,
                                                             "Group3_5",
                                                      ifelse(Event_Time_Hr < 9,
                                                             "Group6_8",
                                                      ifelse(Event_Time_Hr < 12,
                                                             "Group9_11",
                                                      ifelse(Event_Time_Hr < 15,
                                                             "Group12_14",
                                                      ifelse(Event_Time_Hr < 18,
                                                             "Group15_17",
                                                      ifelse(Event_Time_Hr < 21,
                                                             "Group18_20",
                                                      ifelse(Event_Time_Hr < 24,
                                                             "Group21_23"
                                                            )))))))),
                                                         levels = c("Group0_2",
                                                                    "Group3_5",
                                                                    "Group6_8",
                                                                    "Group9_11",
                                                                    "Group12_14",
                                                                    "Group15_17",
                                                                    "Group18_20",
                                                                    "Group21_23"
                                                                   ),
                                                         ordered = TRUE
                                                     )
                         )
rm(AllDays_FirstStopID)
str(AllDays_AddVars)
'data.frame':   2809529 obs. of  50 variables:
 $ group               : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID              : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route               : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt            : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction     : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence       : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID             : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc           : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type          : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description   : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time          : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time      : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time          : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time          : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance   : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude            : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude           : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading             : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG           : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New          : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean        : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator    : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean            : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med             : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean            : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed      : num  -7.94e-04 -1.85e-04 -1.73e-04 1.62e-04 4.75e-05 ...
 $ Lng_MeaLessMed      : num  3.72e-04 -6.78e-04 1.69e-04 4.11e-05 -1.52e-04 ...
 $ RowNum              : int  9715 9716 9674 9673 8168 9701 9829 9828 9667 9829 ...
 $ UniqueLatLng        : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ id                  : chr  "10" "10" "10" "10" ...
 $ adminCode2          : chr  "059" "059" "059" "059" ...
 $ Stop_State          : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County         : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng                 : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance            : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode         : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip            : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ adminName1          : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City           : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ lat                 : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Odometer_Distance_Mi: num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2         : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr       : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth      : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date     : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day      : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr       : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min      : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup  : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
# group_by(AllDays_AddVars,
#          Event_Time_HrGroup
#         ) %>% 
#   summarise(Cnts = n()
#            )
# View(head(filter(AllDays_AddVars,
#                  Event_Time_Hr == 0
#                 ),
#           50
#          )
#     )
# View(head(AllDays_AddVars, 50))

Feature engineering.

Creating more variables. Creating a BusEvent row number for future identification purposes. Then, creating various variables to analyze distance traveled and speed.

AllDays_BusDay <- group_by(AllDays_AddVars,
                           Bus_ID,
                           Event_Time_Date
                          ) %>% 
  mutate(BusDay_EventNum = row_number(),  # used to identify Bus movements on a particular date
         
         Route_Lag1 = lag(Route),  # used in future analyses to identify Route changes
         RouteAlt_Lag1 = lag(RouteAlt),  # used in future analyses to identify RouteAlt (direction) changes
         
         Odometer_Distance_Lag1 = lag(Odometer_Distance),
         
         Latitude_L1 = lag(Latitude),
         Longitude_L1 = lag(Longitude),
         # Lat_Radian = Latitude*pi/180,
         # Long_Radian = Longitude*pi/180,
         # Lat_Radian_L1 = lag(Lat_Radian),
         # Long_Radian_L1 = lag(Long_Radian),
         
         # accounting for potential negative distances
         TravelDistance_Ft = ifelse(Odometer_Distance > Odometer_Distance_Lag1,
                                    Odometer_Distance - Odometer_Distance_Lag1,
                                    NA
                                   ),
         TravelDistance_Mi = TravelDistance_Ft / 5280, #5,280 feet in 1 mile
         
         # TravelDistance_Mi2 = gcd.hf(long1 = Long_Radian_L1,
         #                             lat1 = Lat_Radian_L1,
         #                             long2 = Long_Radian,
         #                             lat2 = Lat_Radian
         #                            ),
         
         TravelDistance_Mi_Hvrs = 
                              # ifelse((is.na(Longitude_L1) | is.na(Latitude_L1)
                              #        ),
                              #        NA,
                              distHaversine(cbind(Longitude_L1, Latitude_L1),
                                            cbind(Longitude, Latitude)
                                           ) * 0.000621371, # 0.000621371 miles = 1 meter
         
         # accounting for potential negative times
         TravelTime_Sec = as.numeric(ifelse(Event_Time > lag(Departure_Time),
                                            Event_Time - lag(Departure_Time),
                                            NA
                                           )
                                    ),
         TravelTime_Hr = TravelTime_Sec / 3600, # 3,600 seconds in 1 hour
         
         # accounting for potential negative or zero travel times
         SpeedAvg_Mph = ifelse(TravelTime_Hr > 0,
                               TravelDistance_Mi / TravelTime_Hr,
                               NA
                              ),
         
         Start_ID = lag(StopID_Clean),
         Start_Desc = lag(Stop_Desc),
         StartStop_ID = ifelse(is.na(Start_ID),
                               paste("NULL", StopID_Clean, sep = "--"),
                               paste(Start_ID, StopID_Clean, sep = "--")
                              )
        ) %>% 
  as.data.frame()
rm(AllDays_AddVars)
str(AllDays_BusDay)
'data.frame':   2809529 obs. of  65 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med               : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med               : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed        : num  -7.94e-04 -1.85e-04 -1.73e-04 1.62e-04 4.75e-05 ...
 $ Lng_MeaLessMed        : num  3.72e-04 -6.78e-04 1.69e-04 4.11e-05 -1.52e-04 ...
 $ RowNum                : int  9715 9716 9674 9673 8168 9701 9829 9828 9667 9829 ...
 $ UniqueLatLng          : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ id                    : chr  "10" "10" "10" "10" ...
 $ adminCode2            : chr  "059" "059" "059" "059" ...
 $ Stop_State            : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County           : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng                   : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance              : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode           : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip              : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ adminName1            : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City             : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ lat                   : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
# summary(AllDays_BusDay)
# View(tail(AllDays_BusDay, 50))

Inspecting for issues with StartStop_ID (where the value is either NA or contains NULL). They ONLY exist when BusDay_EventNum = 1 (which is by design). So everything looks OK.

View(group_by(AllDays_BusDay,
              StartStop_ID
             ) %>% 
       summarise(
         Cnt = n()
       ) %>% 
       arrange(desc(Cnt)
              )
    )
View(filter(AllDays_BusDay,
            (is.na(StartStop_ID) |
              str_detect(StartStop_ID, "NULL")
            ) &
              BusDay_EventNum != 1
           )
    )

Stats (quantiles) overall for TravelDistance_Mi.

Quantiles_dt <- AllDays_BusDay %>% 
  mutate(TD_Mi_q2 = quantile(x = TravelDistance_Mi, probs = 0.02, na.rm = TRUE),
         TD_Mi_q98 = quantile(x = TravelDistance_Mi, probs = 0.98, na.rm = TRUE),
         TT_Sec_q2 = quantile(x = TravelTime_Sec, probs = 0.02, na.rm = TRUE),
         TT_Sec_q98 = quantile(x = TravelTime_Sec, probs = 0.98, na.rm = TRUE),
         TT_Hr_q2 = quantile(x = TravelTime_Hr, probs = 0.02, na.rm = TRUE),
         TT_Hr_q98 = quantile(x = TravelTime_Hr, probs = 0.98, na.rm = TRUE)
        ) %>% 
  data.table()
Stats <- Quantiles_dt %>% 
  mutate(TD_Mi_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_Mean_F = mean(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98],
                             na.rm = TRUE
                            ),
         TD_Mi_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_Med_F = median(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98],
                              na.rm = TRUE
                             ),
         TD_Mi_Cnt = sum(!is.na(TravelDistance_Mi)
                        ),
         TD_Mi_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98]
                                 )
                          ),
            
         TT_Sec_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_Mean_F = mean(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98],
                              na.rm = TRUE
                             ),
         TT_Sec_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_Med_F = median(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98],
                               na.rm = TRUE
                              ),
         TT_Sec_Cnt = sum(!is.na(TravelTime_Sec)
                         ),
         TT_Sec_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98]
                                   )
                           ),
         TT_Hr_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_Mean_F = mean(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98],
                             na.rm = TRUE
                            ),
         TT_Hr_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_Med_F = median(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98],
                              na.rm = TRUE
                             ),
         TT_Hr_Cnt = sum(!is.na(TravelTime_Hr)
                        ),
         TT_Hr_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98]
                                 )
                          )
        ) %>% 
  data.frame()
rm(AllDays_BusDay)
rm(Quantiles_dt)
str(Stats)
'data.frame':   2809529 obs. of  89 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med               : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med               : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed        : num  -7.94e-04 -1.85e-04 -1.73e-04 1.62e-04 4.75e-05 ...
 $ Lng_MeaLessMed        : num  3.72e-04 -6.78e-04 1.69e-04 4.11e-05 -1.52e-04 ...
 $ RowNum                : int  9715 9716 9674 9673 8168 9701 9829 9828 9667 9829 ...
 $ UniqueLatLng          : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ id                    : chr  "10" "10" "10" "10" ...
 $ adminCode2            : chr  "059" "059" "059" "059" ...
 $ Stop_State            : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County           : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng                   : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance              : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode           : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip              : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ adminName1            : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City             : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ lat                   : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
# View(head(Stats, 50))

Stats for StartStop_ID.

Quantiles_SS_dt <- group_by(Stats,
                            StartStop_ID
                           ) %>% 
  mutate(TD_Mi_SS_q5 = quantile(x = TravelDistance_Mi, probs = 0.05, na.rm = TRUE),
         TD_Mi_SS_q95 = quantile(x = TravelDistance_Mi, probs = 0.95, na.rm = TRUE),
         TT_Sec_SS_q5 = quantile(x = TravelTime_Sec, probs = 0.05, na.rm = TRUE),
         TT_Sec_SS_q95 = quantile(x = TravelTime_Sec, probs = 0.95, na.rm = TRUE),
         TT_Hr_SS_q5 = quantile(x = TravelTime_Hr, probs = 0.05, na.rm = TRUE),
         TT_Hr_SS_q95 = quantile(x = TravelTime_Hr, probs = 0.95, na.rm = TRUE)
        ) %>% 
  data.table()
Stats_StSt <- group_by(Quantiles_SS_dt,
                       StartStop_ID
                      ) %>% 
  mutate(TD_Mi_SS_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SS_Mean_F = mean(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95],
                                na.rm = TRUE
                               ),
         TD_Mi_SS_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SS_Med_F = median(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95],
                                 na.rm = TRUE
                                ),
         TD_Mi_SS_Cnt = sum(!is.na(TravelDistance_Mi)
                           ),
         TD_Mi_SS_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95]
                                    )
                             ),
            
         TT_Sec_SS_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SS_Mean_F = mean(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95],
                                 na.rm = TRUE
                                ),
         TT_Sec_SS_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SS_Med_F = median(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95],
                                  na.rm = TRUE
                                 ),
         TT_Sec_SS_Cnt = sum(!is.na(TravelTime_Sec)),
         TT_Sec_SS_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95]
                                     )
                              ),
         TT_Hr_SS_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SS_Mean_F = mean(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95],
                                na.rm = TRUE
                               ),
         TT_Hr_SS_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SS_Med_F = median(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95],
                                 na.rm = TRUE
                                ),
         TT_Hr_SS_Cnt = sum(!is.na(TravelTime_Hr)),
         TT_Hr_SS_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95]
                                    )
                             )
        ) %>% 
  data.frame()
rm(Stats)
rm(Quantiles_SS_dt)
str(Stats_StSt)
'data.frame':   2809529 obs. of  113 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med               : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med               : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed        : num  -7.94e-04 -1.85e-04 -1.73e-04 1.62e-04 4.75e-05 ...
 $ Lng_MeaLessMed        : num  3.72e-04 -6.78e-04 1.69e-04 4.11e-05 -1.52e-04 ...
 $ RowNum                : int  9715 9716 9674 9673 8168 9701 9829 9828 9667 9829 ...
 $ UniqueLatLng          : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ id                    : chr  "10" "10" "10" "10" ...
 $ adminCode2            : chr  "059" "059" "059" "059" ...
 $ Stop_State            : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County           : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng                   : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance              : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode           : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip              : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ adminName1            : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City             : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ lat                   : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
  [list output truncated]
# View(head(Stats_StSt, 50))

Stats for StartStop_ID with Event_Time_HrGroup.

Quantiles_SSHG_dt <- group_by(Stats_StSt,
                              StartStop_ID,
                              Event_Time_HrGroup
                             ) %>% 
  mutate(TD_Mi_SSHG_q5 = quantile(x = TravelDistance_Mi, probs = 0.05, na.rm = TRUE),
         TD_Mi_SSHG_q95 = quantile(x = TravelDistance_Mi, probs = 0.95, na.rm = TRUE),
         TT_Sec_SSHG_q5 = quantile(x = TravelTime_Sec, probs = 0.05, na.rm = TRUE),
         TT_Sec_SSHG_q95 = quantile(x = TravelTime_Sec, probs = 0.95, na.rm = TRUE),
         TT_Hr_SSHG_q5 = quantile(x = TravelTime_Hr, probs = 0.05, na.rm = TRUE),
         TT_Hr_SSHG_q95 = quantile(x = TravelTime_Hr, probs = 0.95, na.rm = TRUE)
        ) %>% 
  data.table()
Stats_StSt_HrGrp <- group_by(Quantiles_SSHG_dt,
                             StartStop_ID,
                             Event_Time_HrGroup
                            ) %>% 
  mutate(TD_Mi_SSHG_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SSHG_Mean_F = mean(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95],
                                  na.rm = TRUE
                                 ),
         TD_Mi_SSHG_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SSHG_Med_F = median(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TD_Mi_SSHG_Cnt = sum(!is.na(TravelDistance_Mi)
                             ),
         TD_Mi_SSHG_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95]
                                      )
                               ),
            
         TT_Sec_SSHG_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SSHG_Mean_F = mean(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TT_Sec_SSHG_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SSHG_Med_F = median(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95],
                                    na.rm = TRUE
                                   ),
         TT_Sec_SSHG_Cnt = sum(!is.na(TravelTime_Sec)),
         TT_Sec_SSHG_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95]
                                       )
                                ),
         TT_Hr_SSHG_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SSHG_Mean_F = mean(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95],
                                  na.rm = TRUE
                                 ),
         TT_Hr_SSHG_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SSHG_Med_F = median(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TT_Hr_SSHG_Cnt = sum(!is.na(TravelTime_Hr)),
         TT_Hr_SSHG_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95]
                                      )
                               )
        ) %>% 
  data.frame()
rm(Stats_StSt)
rm(Quantiles_SSHG_dt)
str(Stats_StSt_HrGrp)
'data.frame':   2809529 obs. of  137 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med               : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med               : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed        : num  -7.94e-04 -1.85e-04 -1.73e-04 1.62e-04 4.75e-05 ...
 $ Lng_MeaLessMed        : num  3.72e-04 -6.78e-04 1.69e-04 4.11e-05 -1.52e-04 ...
 $ RowNum                : int  9715 9716 9674 9673 8168 9701 9829 9828 9667 9829 ...
 $ UniqueLatLng          : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ id                    : chr  "10" "10" "10" "10" ...
 $ adminCode2            : chr  "059" "059" "059" "059" ...
 $ Stop_State            : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County           : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng                   : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance              : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode           : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip              : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ adminName1            : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City             : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ lat                   : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
  [list output truncated]
# View(head(Stats_StSt_HrGrp, 50))

Feature engineering.

Creating a BusEventRoute row number, and a RouteAlt_Lag1 indicator for future identification purposes.

# rm(Quantiles_dt)
# rm(Quantiles_SS_dt)
# rm(AllDays_BusDay)
# rm(Quantiles_SSHG_dt)
# rm(Stats_StSt)
# AllDays_BusDayRoute <- group_by(Stats_StSt_HrGrp,
#                                 Bus_ID,
#                                 Event_Time_Date,
#                                 Route
#                                ) %>% 
#   mutate(RouteAlt_Lag2 = lag(RouteAlt)  # used in future analyses to identify RouteAlt (direction) changes
#          
#          # Odometer_Distance_Lag1 = lag(Odometer_Distance),
#          # 
#          # # accounting for potential negative distances
#          # TravelDistance_Ft = ifelse(Odometer_Distance >= Odometer_Distance_Lag1,
#          #                            Odometer_Distance - Odometer_Distance_Lag1,
#          #                            NA
#          #                           ),
#          # TravelDistance_Mi = TravelDistance_Ft / 5280, #5,280 feet in 1 mile
#          # 
#          # # accounting for potential negative times
#          # TravelTime_Sec = as.numeric(ifelse(Event_Time >= lag(Departure_Time),
#          #                                    Event_Time - lag(Departure_Time),
#          #                                    NA
#          #                                   )
#          #                            ),
#          # TravelTime_Hr = TravelTime_Sec / 3600, # 3,600 seconds in 1 hour
#          # 
#          # # accounting for potential negative or zero travel times
#          # SpeedAvg_Mph = ifelse(TravelTime_Hr > 0,
#          #                       TravelDistance_Mi / TravelTime_Hr,
#          #                       NA
#          #                      )
#         ) %>% 
#   data.frame()
# 
# rm(Stats_StSt_HrGrp)
# str(AllDays_BusDayRoute)

Feature engineering.

Calculating a variable to know if the RouteAlt changed. Could be useful in helping identifying weirdness in calculated distances and speeds.

# rm(Stats_StSt_HrGrp)
AllDays_DirChange <- Stats_StSt_HrGrp %>%  # AllDays_BusDayRoute %>% 
  mutate(RteChange = ifelse(Route == Route_Lag1,
                            "Same",
                            "Change"
                           ),
         RteChange2 = factor(ifelse(is.na(RteChange),
                                    "Change",
                                    RteChange
                                   )
                            ),
         DirChange = ifelse(RouteAlt == RouteAlt_Lag1,
                            "Same",
                            "Change"
                           ),
         DirChange2 = factor(ifelse(is.na(DirChange),
                                    "Change",
                                    DirChange
                                   )
                            )
        )
# rm(AllDays_BusDayRoute)
rm(Stats_StSt_HrGrp)
str(AllDays_DirChange)
'data.frame':   2809529 obs. of  141 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Lat_Mean              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lat_Med               : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Lng_Mean              : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lng_Med               : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Lat_MeaLessMed        : num  -7.94e-04 -1.85e-04 -1.73e-04 1.62e-04 4.75e-05 ...
 $ Lng_MeaLessMed        : num  3.72e-04 -6.78e-04 1.69e-04 4.11e-05 -1.52e-04 ...
 $ RowNum                : int  9715 9716 9674 9673 8168 9701 9829 9828 9667 9829 ...
 $ UniqueLatLng          : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ id                    : chr  "10" "10" "10" "10" ...
 $ adminCode2            : chr  "059" "059" "059" "059" ...
 $ Stop_State            : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County           : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ lng                   : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ distance              : num  0 0 0 0 0 0 0 0 0 0 ...
 $ countryCode           : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_Zip              : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ adminName1            : Factor w/ 3 levels "District of Columbia",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_City             : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ lat                   : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
  [list output truncated]
View(filter(AllDays_DirChange,
            between(RowNum_OG, 2570060, 2570080)
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
             )
    )

Re-ordering the variables to ease with comprehension.

AllDays_NewOrder <-  select(AllDays_DirChange,
                            RowNum_OG,
                            UniqueLatLng,
                            group,
                            StartStop_ID,
                            BusDay_EventNum,
                            Bus_ID,
                            Route,
                            RteChange2,
                            RouteAlt,
                            # RouteAlt_Lag1,
                            DirChange2,
                            Route_Direction,
                            Stop_Sequence,
                            Start_ID,
                            Start_Desc,
                            # Stop_ID,
                            StopID_Clean,
                            StopID_Indicator,
                            Stop_Desc,
                            countryCode,
                            Stop_State,
                            Stop_County,
                            Stop_City,
                            Stop_Zip,
                            Event_Type,
                            Event_Description,
                            Event_Time_Yr,
                            Event_Time_Mth,
                            Event_Time_Date,
                            Event_Time_Day,
                            Event_Time_Hr,
                            Event_Time_HrGroup,
                            Event_Time_Min,
                            Event_Time,
                            Departure_Time,
                            Dwell_Time,
                            Dwell_Time2,
                            Delta_Time,
                            Latitude,
                            Longitude,
                            Heading,
                            Odometer_Distance,
                            Odometer_Distance_Lag1,
                            Odometer_Distance_Mi,
                            TravelDistance_Ft,
                            TravelDistance_Mi,
                            TravelDistance_Mi_Hvrs,
                            TD_Mi_q2,
                            TD_Mi_q98,
                            TD_Mi_SS_q5,
                            TD_Mi_SS_q95,
                            TD_Mi_SSHG_q5,
                            TD_Mi_SSHG_q95,
                            TD_Mi_Mean,
                            TD_Mi_Mean_F,
                            TD_Mi_SS_Mean,
                            TD_Mi_SS_Mean_F,
                            TD_Mi_SSHG_Mean,
                            TD_Mi_SSHG_Mean_F,
                            TD_Mi_Med,
                            TD_Mi_Med_F,
                            TD_Mi_SS_Med,
                            TD_Mi_SS_Med_F,
                            TD_Mi_SSHG_Med,
                            TD_Mi_SSHG_Med_F,
                            TD_Mi_Cnt,
                            TD_Mi_Cnt_F,
                            TD_Mi_SS_Cnt,
                            TD_Mi_SS_Cnt_F,
                            TD_Mi_SSHG_Cnt,
                            TD_Mi_SSHG_Cnt_F,
                            TravelTime_Sec,
                            TT_Sec_q2,
                            TT_Sec_q98,
                            TT_Sec_SS_q5,
                            TT_Sec_SS_q95,
                            TT_Sec_SSHG_q5,
                            TT_Sec_SSHG_q95,
                            TT_Sec_Mean,
                            TT_Sec_Mean_F,
                            TT_Sec_SS_Mean,
                            TT_Sec_SS_Mean_F,
                            TT_Sec_SSHG_Mean,
                            TT_Sec_SSHG_Mean_F,
                            TT_Sec_Med,
                            TT_Sec_Med_F,
                            TT_Sec_SS_Med,
                            TT_Sec_SS_Med_F,
                            TT_Sec_SSHG_Med,
                            TT_Sec_SSHG_Med_F,
                            TT_Sec_Cnt,
                            TT_Sec_Cnt_F,
                            TT_Sec_SS_Cnt,
                            TT_Sec_SS_Cnt_F,
                            TT_Sec_SSHG_Cnt,
                            TT_Sec_SSHG_Cnt_F,
                            TravelTime_Hr,
                            TT_Hr_q2,
                            TT_Hr_q98,
                            TT_Hr_SS_q5,
                            TT_Hr_SS_q95,
                            TT_Hr_SSHG_q5,
                            TT_Hr_SSHG_q95,
                            TT_Hr_Mean,
                            TT_Hr_Mean_F,
                            TT_Hr_SS_Mean,
                            TT_Hr_SS_Mean_F,
                            TT_Hr_SSHG_Mean,
                            TT_Hr_SSHG_Mean_F,
                            TT_Hr_Med,
                            TT_Hr_Med_F,
                            TT_Hr_SS_Med,
                            TT_Hr_SS_Med_F,
                            TT_Hr_SSHG_Med,
                            TT_Hr_SSHG_Med_F,
                            TT_Hr_Cnt,
                            TT_Hr_Cnt_F,
                            TT_Hr_SS_Cnt,
                            TT_Hr_SS_Cnt_F,
                            TT_Hr_SSHG_Cnt,
                            TT_Hr_SSHG_Cnt_F,
                            SpeedAvg_Mph
                           )
rm(AllDays_DirChange)
str(select(AllDays_NewOrder,
           -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
          )
   )
'data.frame':   2809529 obs. of  48 variables:
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ UniqueLatLng          : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2            : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2            : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ countryCode           : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_State            : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County           : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_City             : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ Stop_Zip              : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
str(AllDays_NewOrder)
'data.frame':   2809529 obs. of  120 variables:
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ UniqueLatLng          : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2            : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2            : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ countryCode           : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_State            : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County           : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_City             : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ Stop_Zip              : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SSHG_Mean       : num  NaN 0.442 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Mean_F     : num  NaN 0.491 0.242 0.7 0.182 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SSHG_Med        : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Med_F      : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TD_Mi_SSHG_Cnt        : int  0 7 1 1 1 23 6 29 28 3 ...
 $ TD_Mi_SSHG_Cnt_F      : int  0 5 1 1 1 19 4 25 24 1 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SSHG_Mean      : num  NaN 202 37 25 190 ...
 $ TT_Sec_SSHG_Mean_F    : num  NaN 226 37 25 190 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SSHG_Med       : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_SSHG_Med_F     : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Sec_SSHG_Cnt       : int  0 7 1 1 1 35 6 36 35 3 ...
 $ TT_Sec_SSHG_Cnt_F     : int  0 5 1 1 1 31 4 32 32 1 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
  [list output truncated]
# View(head(AllDays_NewOrder, 500))
# View(tail(AllDays_NewOrder, 500))

Summarizing the data to help spot anomolies.

View(group_by(AllDays_NewOrder,
              Stop_City) %>% 
       summarise(Cnt_Num = n(),
                 Cnt_Pct = 100*Cnt_Num / (nrow(AllDays_NewOrder)
                                         )
                ) %>% 
       arrange(desc(Cnt_Num))
)
summary(AllDays_NewOrder)
   RowNum_OG       UniqueLatLng       group      StartStop_ID      
 Min.   :      1   Length:2809529     1:559521   Length:2809529    
 1st Qu.: 784722   Class :character   2:561389   Class :character  
 Median :1563300   Mode  :character   3:567794   Mode  :character  
 Mean   :1562504                      4:559180                     
 3rd Qu.:2337981                      5:561645                     
 Max.   :3119443                                                   
                                                                   
 BusDay_EventNum      Bus_ID        Route            RteChange2     
 Min.   :   1.0   Min.   :  11   Length:2809529     Change:  23772  
 1st Qu.: 113.0   1st Qu.:2922   Class :character   Same  :2785757  
 Median : 248.0   Median :6195   Mode  :character                   
 Mean   : 290.5   Mean   :5382                                      
 3rd Qu.: 428.0   3rd Qu.:7104                                      
 Max.   :1344.0   Max.   :8105                                      
                                                                    
    RouteAlt        DirChange2      Route_Direction   Stop_Sequence   
 2      :1128810   Change:  65126   SOUTH   :739235   Min.   :  1.00  
 1      :1065425   Same  :2744403   NORTH   :735203   1st Qu.: 12.00  
 3      : 260372                    WEST    :649706   Median : 24.00  
 4      : 130801                    EAST    :628074   Mean   : 26.83  
 5      :  75039                    LOOP    : 35611   3rd Qu.: 39.00  
 6      :  56408                    CLOCKWIS: 10671   Max.   :104.00  
 (Other):  92674                    (Other) : 11029                   
   Start_ID          Start_Desc        StopID_Clean       StopID_Indicator
 Length:2809529     Length:2809529     Length:2809529     ID_Bad:  18948  
 Class :character   Class :character   Class :character   ID_OK :2790581  
 Mode  :character   Mode  :character   Mode  :character                   
                                                                          
                                                                          
                                                                          
                                                                          
  Stop_Desc         countryCode    Stop_State                   Stop_County     
 Length:2809529     US  :2808431   DC  :1297006   District of Columbia:1297006  
 Class :character   NA's:   1098   MD  : 982401   Prince George's     : 589193  
 Mode  :character                  VA  : 529024   Montgomery          : 391422  
                                   NA's:   1098   Fairfax             : 204558  
                                                  Arlington           : 198618  
                                                  (Other)             : 127634  
                                                  NA's                :   1098  
         Stop_City          Stop_Zip         Event_Type 
 Washington   :1296626   20020  : 156333   Min.   :3.0  
 Silver Spring: 227570   20032  : 117215   1st Qu.:3.0  
 Arlington    : 198360   20019  : 116560   Median :4.0  
 Hyattsville  : 166930   20011  : 114518   Mean   :3.6  
 Alexandria   : 103776   20002  : 101086   3rd Qu.:4.0  
 (Other)      : 815169   (Other):2202719   Max.   :5.0  
 NA's         :   1098   NA's   :   1098                
                                          Event_Description   Event_Time_Yr 
 Serviced Stop                                     :1127366   Min.   :2016  
 Unknown Stop                                      :   2579   1st Qu.:2016  
 UnServiced Stop                                   :1679584   Median :2016  
                                                              Mean   :2016  
                                                              3rd Qu.:2016  
                                                              Max.   :2016  
                                                                            
 Event_Time_Mth Event_Time_Date Event_Time_Day Event_Time_Hr    Event_Time_HrGroup
 Min.   :10     Min.   :3.000   Sun  :     0   Min.   : 0.00   Group6_8  :611612  
 1st Qu.:10     1st Qu.:4.000   Mon  :559521   1st Qu.: 8.00   Group15_17:560103  
 Median :10     Median :5.000   Tues :561389   Median :13.00   Group18_20:461056  
 Mean   :10     Mean   :5.001   Wed  :567794   Mean   :12.97   Group9_11 :396514  
 3rd Qu.:10     3rd Qu.:6.000   Thurs:559180   3rd Qu.:18.00   Group12_14:353603  
 Max.   :10     Max.   :7.000   Fri  :561645   Max.   :23.00   Group21_23:244522  
                                Sat  :     0                   (Other)   :182119  
 Event_Time_Min    Event_Time                  Departure_Time               
 Min.   : 0.00   Min.   :2016-10-03 00:00:00   Min.   :2016-10-03 00:00:00  
 1st Qu.:14.00   1st Qu.:2016-10-04 08:36:14   1st Qu.:2016-10-04 08:36:20  
 Median :29.00   Median :2016-10-05 13:49:29   Median :2016-10-05 13:49:38  
 Mean   :29.43   Mean   :2016-10-05 13:29:21   Mean   :2016-10-05 13:29:28  
 3rd Qu.:44.00   3rd Qu.:2016-10-06 17:58:06   3rd Qu.:2016-10-06 17:58:13  
 Max.   :59.00   Max.   :2016-10-07 23:59:59   Max.   :2016-10-08 00:12:31  
                                                                            
   Dwell_Time       Dwell_Time2         Delta_Time         Latitude    
 Min.   :   0.00   Min.   :   0.000   Min.   :-5606.0   Min.   : 0.00  
 1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   14.0   1st Qu.:38.86  
 Median :   0.00   Median :   0.000   Median :  157.0   Median :38.90  
 Mean   :  12.56   Mean   :   6.359   Mean   :  268.8   Mean   :38.91  
 3rd Qu.:   5.00   3rd Qu.:   4.000   3rd Qu.:  396.0   3rd Qu.:38.96  
 Max.   :6205.00   Max.   :6205.000   Max.   : 9426.0   Max.   :39.19  
                                                                       
   Longitude         Heading      Odometer_Distance  Odometer_Distance_Lag1
 Min.   :-77.45   Min.   :  0.0   Min.   :       0   Min.   :       0      
 1st Qu.:-77.07   1st Qu.: 89.0   1st Qu.:  177595   1st Qu.:  177326      
 Median :-77.02   Median :180.0   Median :  377510   Median :  376934      
 Mean   :-77.02   Mean   :176.9   Mean   :  426254   Mean   :  425713      
 3rd Qu.:-76.97   3rd Qu.:269.0   3rd Qu.:  623667   3rd Qu.:  622879      
 Max.   :  0.00   Max.   :360.0   Max.   :11108034   Max.   :10853226      
                                                     NA's   :6528          
 Odometer_Distance_Mi TravelDistance_Ft TravelDistance_Mi TravelDistance_Mi_Hvrs
 Min.   :   0.00      Min.   :      1   Min.   :  0.0     Min.   : 0.000        
 1st Qu.:  33.64      1st Qu.:    699   1st Qu.:  0.1     1st Qu.: 0.106        
 Median :  71.50      Median :   1044   Median :  0.2     Median : 0.142        
 Mean   :  80.73      Mean   :   1624   Mean   :  0.3     Mean   : 0.201        
 3rd Qu.: 118.12      3rd Qu.:   1518   3rd Qu.:  0.3     3rd Qu.: 0.193        
 Max.   :2103.79      Max.   :1323464   Max.   :250.7     Max.   :24.407        
                      NA's   :322734    NA's   :322734    NA's   :6528          
    TD_Mi_q2         TD_Mi_q98       TD_Mi_SS_q5       TD_Mi_SS_q95    
 Min.   :0.05208   Min.   :0.9585   Min.   :  0.000   Min.   :  0.000  
 1st Qu.:0.05208   1st Qu.:0.9585   1st Qu.:  0.086   1st Qu.:  0.262  
 Median :0.05208   Median :0.9585   Median :  0.104   Median :  0.326  
 Mean   :0.05208   Mean   :0.9585   Mean   :  0.164   Mean   :  0.488  
 3rd Qu.:0.05208   3rd Qu.:0.9585   3rd Qu.:  0.139   3rd Qu.:  0.436  
 Max.   :0.05208   Max.   :0.9585   Max.   :219.163   Max.   :246.949  
                                    NA's   :24757     NA's   :24757    
 TD_Mi_SSHG_q5    TD_Mi_SSHG_q95     TD_Mi_Mean      TD_Mi_Mean_F   
 Min.   :  0.00   Min.   :  0.00   Min.   :0.3076   Min.   :0.2318  
 1st Qu.:  0.09   1st Qu.:  0.25   1st Qu.:0.3076   1st Qu.:0.2318  
 Median :  0.11   Median :  0.31   Median :0.3076   Median :0.2318  
 Mean   :  0.18   Mean   :  0.47   Mean   :0.3076   Mean   :0.2318  
 3rd Qu.:  0.15   3rd Qu.:  0.42   3rd Qu.:0.3076   3rd Qu.:0.2318  
 Max.   :250.66   Max.   :250.66   Max.   :0.3076   Max.   :0.2318  
 NA's   :35629    NA's   :35629                                     
 TD_Mi_SS_Mean     TD_Mi_SS_Mean_F   TD_Mi_SSHG_Mean  TD_Mi_SSHG_Mean_F
 Min.   :  0.000   Min.   :  0.000   Min.   :  0.00   Min.   :  0.00   
 1st Qu.:  0.172   1st Qu.:  0.166   1st Qu.:  0.17   1st Qu.:  0.16   
 Median :  0.212   Median :  0.207   Median :  0.21   Median :  0.21   
 Mean   :  0.307   Mean   :  0.291   Mean   :  0.31   Mean   :  0.29   
 3rd Qu.:  0.267   3rd Qu.:  0.260   3rd Qu.:  0.27   3rd Qu.:  0.26   
 Max.   :219.163   Max.   :219.163   Max.   :250.66   Max.   :250.66   
 NA's   :24757     NA's   :27919     NA's   :35629    NA's   :44458    
   TD_Mi_Med       TD_Mi_Med_F      TD_Mi_SS_Med     TD_Mi_SS_Med_F   
 Min.   :0.1977   Min.   :0.1977   Min.   :  0.000   Min.   :  0.000  
 1st Qu.:0.1977   1st Qu.:0.1977   1st Qu.:  0.146   1st Qu.:  0.146  
 Median :0.1977   Median :0.1977   Median :  0.196   Median :  0.196  
 Mean   :0.1977   Mean   :0.1977   Mean   :  0.288   Mean   :  0.282  
 3rd Qu.:0.1977   3rd Qu.:0.1977   3rd Qu.:  0.265   3rd Qu.:  0.265  
 Max.   :0.1977   Max.   :0.1977   Max.   :219.163   Max.   :219.163  
                                   NA's   :24757     NA's   :27919    
 TD_Mi_SSHG_Med   TD_Mi_SSHG_Med_F   TD_Mi_Cnt        TD_Mi_Cnt_F     
 Min.   :  0.00   Min.   :  0.00   Min.   :2486795   Min.   :2387406  
 1st Qu.:  0.14   1st Qu.:  0.14   1st Qu.:2486795   1st Qu.:2387406  
 Median :  0.20   Median :  0.20   Median :2486795   Median :2387406  
 Mean   :  0.29   Mean   :  0.28   Mean   :2486795   Mean   :2387406  
 3rd Qu.:  0.27   3rd Qu.:  0.27   3rd Qu.:2486795   3rd Qu.:2387406  
 Max.   :250.66   Max.   :250.66   Max.   :2486795   Max.   :2387406  
 NA's   :35629    NA's   :44458                                       
  TD_Mi_SS_Cnt    TD_Mi_SS_Cnt_F   TD_Mi_SSHG_Cnt   TD_Mi_SSHG_Cnt_F
 Min.   :   0.0   Min.   :   0.0   Min.   :  0.00   Min.   :  0.00  
 1st Qu.: 163.0   1st Qu.: 146.0   1st Qu.: 26.00   1st Qu.: 22.00  
 Median : 280.0   Median : 252.0   Median : 45.00   Median : 39.00  
 Mean   : 347.4   Mean   : 312.7   Mean   : 57.27   Mean   : 50.85  
 3rd Qu.: 456.0   3rd Qu.: 411.0   3rd Qu.: 75.00   3rd Qu.: 67.00  
 Max.   :1543.0   Max.   :1388.0   Max.   :663.00   Max.   :595.00  
                                                                    
 TravelTime_Sec      TT_Sec_q2    TT_Sec_q98   TT_Sec_SS_q5      TT_Sec_SS_q95     
 Min.   :    1.0   Min.   :10   Min.   :349   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   25.0   1st Qu.:10   1st Qu.:349   1st Qu.:   15.00   1st Qu.:   48.00  
 Median :   39.0   Median :10   Median :349   Median :   22.00   Median :   80.05  
 Mean   :  104.9   Mean   :10   Mean   :349   Mean   :   61.26   Mean   :  183.28  
 3rd Qu.:   72.0   3rd Qu.:10   3rd Qu.:349   3rd Qu.:   34.00   3rd Qu.:  134.60  
 Max.   :60750.0   Max.   :10   Max.   :349   Max.   :60750.00   Max.   :60750.00  
 NA's   :6641                                 NA's   :6531       NA's   :6531      
 TT_Sec_SSHG_q5     TT_Sec_SSHG_q95     TT_Sec_Mean    TT_Sec_Mean_F  
 Min.   :    1.00   Min.   :    1.00   Min.   :104.9   Min.   :56.61  
 1st Qu.:   16.00   1st Qu.:   43.80   1st Qu.:104.9   1st Qu.:56.61  
 Median :   23.40   Median :   72.95   Median :104.9   Median :56.61  
 Mean   :   67.33   Mean   :  169.21   Mean   :104.9   Mean   :56.61  
 3rd Qu.:   36.70   3rd Qu.:  123.65   3rd Qu.:104.9   3rd Qu.:56.61  
 Max.   :60750.00   Max.   :60750.00   Max.   :104.9   Max.   :56.61  
 NA's   :6535       NA's   :6535                                      
 TT_Sec_SS_Mean     TT_Sec_SS_Mean_F   TT_Sec_SSHG_Mean   TT_Sec_SSHG_Mean_F
 Min.   :    1.00   Min.   :    1.00   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   29.06   1st Qu.:   27.54   1st Qu.:   28.38   1st Qu.:   27.21  
 Median :   44.16   Median :   41.91   Median :   43.38   Median :   41.48  
 Mean   :  104.88   Mean   :   91.34   Mean   :  104.88   Mean   :   93.53  
 3rd Qu.:   73.30   3rd Qu.:   69.25   3rd Qu.:   72.93   3rd Qu.:   70.12  
 Max.   :60750.00   Max.   :60750.00   Max.   :60750.00   Max.   :60750.00  
 NA's   :6531       NA's   :10519      NA's   :6535       NA's   :12811     
   TT_Sec_Med  TT_Sec_Med_F TT_Sec_SS_Med      TT_Sec_SS_Med_F   
 Min.   :39   Min.   :39    Min.   :    1.00   Min.   :    1.00  
 1st Qu.:39   1st Qu.:39    1st Qu.:   26.00   1st Qu.:   26.00  
 Median :39   Median :39    Median :   39.00   Median :   39.00  
 Mean   :39   Mean   :39    Mean   :   91.55   Mean   :   84.82  
 3rd Qu.:39   3rd Qu.:39    3rd Qu.:   65.00   3rd Qu.:   65.00  
 Max.   :39   Max.   :39    Max.   :60750.00   Max.   :60750.00  
                            NA's   :6531       NA's   :10519     
 TT_Sec_SSHG_Med    TT_Sec_SSHG_Med_F    TT_Sec_Cnt       TT_Sec_Cnt_F    
 Min.   :    1.00   Min.   :    1.00   Min.   :2802888   Min.   :2705189  
 1st Qu.:   26.00   1st Qu.:   26.00   1st Qu.:2802888   1st Qu.:2705189  
 Median :   39.00   Median :   38.50   Median :2802888   Median :2705189  
 Mean   :   94.94   Mean   :   88.44   Mean   :2802888   Mean   :2705189  
 3rd Qu.:   67.00   3rd Qu.:   66.50   3rd Qu.:2802888   3rd Qu.:2705189  
 Max.   :60750.00   Max.   :60750.00   Max.   :2802888   Max.   :2705189  
 NA's   :6535       NA's   :12811                                         
 TT_Sec_SS_Cnt    TT_Sec_SS_Cnt_F  TT_Sec_SSHG_Cnt  TT_Sec_SSHG_Cnt_F
 Min.   :   0.0   Min.   :   0.0   Min.   :  0.00   Min.   :  0.00   
 1st Qu.: 194.0   1st Qu.: 177.0   1st Qu.: 29.00   1st Qu.: 26.00   
 Median : 310.0   Median : 282.0   Median : 51.00   Median : 46.00   
 Mean   : 384.4   Mean   : 349.8   Mean   : 63.46   Mean   : 57.09   
 3rd Qu.: 497.0   3rd Qu.: 452.0   3rd Qu.: 83.00   3rd Qu.: 74.00   
 Max.   :1664.0   Max.   :1523.0   Max.   :691.00   Max.   :634.00   
                                                                     
 TravelTime_Hr       TT_Hr_q2          TT_Hr_q98        TT_Hr_SS_q5    
 Min.   : 0.000   Min.   :0.002778   Min.   :0.09694   Min.   : 0.000  
 1st Qu.: 0.007   1st Qu.:0.002778   1st Qu.:0.09694   1st Qu.: 0.004  
 Median : 0.011   Median :0.002778   Median :0.09694   Median : 0.006  
 Mean   : 0.029   Mean   :0.002778   Mean   :0.09694   Mean   : 0.017  
 3rd Qu.: 0.020   3rd Qu.:0.002778   3rd Qu.:0.09694   3rd Qu.: 0.009  
 Max.   :16.875   Max.   :0.002778   Max.   :0.09694   Max.   :16.875  
 NA's   :6641                                          NA's   :6531    
  TT_Hr_SS_q95    TT_Hr_SSHG_q5    TT_Hr_SSHG_q95     TT_Hr_Mean     
 Min.   : 0.000   Min.   : 0.000   Min.   : 0.000   Min.   :0.02913  
 1st Qu.: 0.013   1st Qu.: 0.004   1st Qu.: 0.012   1st Qu.:0.02913  
 Median : 0.022   Median : 0.006   Median : 0.020   Median :0.02913  
 Mean   : 0.051   Mean   : 0.019   Mean   : 0.047   Mean   :0.02913  
 3rd Qu.: 0.037   3rd Qu.: 0.010   3rd Qu.: 0.034   3rd Qu.:0.02913  
 Max.   :16.875   Max.   :16.875   Max.   :16.875   Max.   :0.02913  
 NA's   :6531     NA's   :6535     NA's   :6535                      
  TT_Hr_Mean_F     TT_Hr_SS_Mean    TT_Hr_SS_Mean_F  TT_Hr_SSHG_Mean 
 Min.   :0.01573   Min.   : 0.000   Min.   : 0.000   Min.   : 0.000  
 1st Qu.:0.01573   1st Qu.: 0.008   1st Qu.: 0.008   1st Qu.: 0.008  
 Median :0.01573   Median : 0.012   Median : 0.012   Median : 0.012  
 Mean   :0.01573   Mean   : 0.029   Mean   : 0.025   Mean   : 0.029  
 3rd Qu.:0.01573   3rd Qu.: 0.020   3rd Qu.: 0.019   3rd Qu.: 0.020  
 Max.   :0.01573   Max.   :16.875   Max.   :16.875   Max.   :16.875  
                   NA's   :6531     NA's   :10532    NA's   :6535    
 TT_Hr_SSHG_Mean_F   TT_Hr_Med        TT_Hr_Med_F       TT_Hr_SS_Med   
 Min.   : 0.000    Min.   :0.01083   Min.   :0.01083   Min.   : 0.000  
 1st Qu.: 0.008    1st Qu.:0.01083   1st Qu.:0.01083   1st Qu.: 0.007  
 Median : 0.012    Median :0.01083   Median :0.01083   Median : 0.011  
 Mean   : 0.026    Mean   :0.01083   Mean   :0.01083   Mean   : 0.025  
 3rd Qu.: 0.019    3rd Qu.:0.01083   3rd Qu.:0.01083   3rd Qu.: 0.018  
 Max.   :16.875    Max.   :0.01083   Max.   :0.01083   Max.   :16.875  
 NA's   :12895                                         NA's   :6531    
 TT_Hr_SS_Med_F   TT_Hr_SSHG_Med   TT_Hr_SSHG_Med_F   TT_Hr_Cnt      
 Min.   : 0.000   Min.   : 0.000   Min.   : 0.000   Min.   :2802888  
 1st Qu.: 0.007   1st Qu.: 0.007   1st Qu.: 0.007   1st Qu.:2802888  
 Median : 0.011   Median : 0.011   Median : 0.011   Median :2802888  
 Mean   : 0.024   Mean   : 0.026   Mean   : 0.025   Mean   :2802888  
 3rd Qu.: 0.018   3rd Qu.: 0.019   3rd Qu.: 0.018   3rd Qu.:2802888  
 Max.   :16.875   Max.   :16.875   Max.   :16.875   Max.   :2802888  
 NA's   :10532    NA's   :6535     NA's   :12895                     
  TT_Hr_Cnt_F       TT_Hr_SS_Cnt    TT_Hr_SS_Cnt_F   TT_Hr_SSHG_Cnt  
 Min.   :2705189   Min.   :   0.0   Min.   :   0.0   Min.   :  0.00  
 1st Qu.:2705189   1st Qu.: 194.0   1st Qu.: 176.0   1st Qu.: 29.00  
 Median :2705189   Median : 310.0   Median : 282.0   Median : 51.00  
 Mean   :2705189   Mean   : 384.4   Mean   : 349.6   Mean   : 63.46  
 3rd Qu.:2705189   3rd Qu.: 497.0   3rd Qu.: 452.0   3rd Qu.: 83.00  
 Max.   :2705189   Max.   :1664.0   Max.   :1523.0   Max.   :691.00  
                                                                     
 TT_Hr_SSHG_Cnt_F  SpeedAvg_Mph    
 Min.   :  0.00   Min.   :    0.0  
 1st Qu.: 26.00   1st Qu.:   10.1  
 Median : 46.00   Median :   16.7  
 Mean   : 57.05   Mean   :   26.5  
 3rd Qu.: 74.00   3rd Qu.:   31.2  
 Max.   :634.00   Max.   :22924.1  
                  NA's   :322762   

Investigation of TravelDistance_Mi.

View(TravDistMi_Pctiles): 99% of TravelDistance_Mi are about 1 mile or less…but some weird TravelDistance_Mi values (e.g., 584 miles traveled) exist.

TravDistMi_Ntile <- as.data.frame(AllDays_NewOrder$TravelDistance_Mi) %>% 
  mutate(#Pctile = ntile(AllDays_NewOrder$TravelDistance_Mi, 100),
         #MinR = min_rank(AllDays_NewOrder$TravelDistance_Mi),
         PctR = percent_rank(AllDays_NewOrder$TravelDistance_Mi),
         PctR_Round = round(PctR, 2)
        ) 
colnames(TravDistMi_Ntile)[1] <- "TravelDistance_Mi"
# str(TravDistMi_Ntile)
TravDistMi_Ntile_Rows <- nrow(TravDistMi_Ntile)
# View(tail(TravDistMi_Ntile, 500))
TravDistMi_Pctiles <- group_by(TravDistMi_Ntile,
                               PctR_Round
                              ) %>% 
  summarise(
    MinTravDistMiAtPctile = min(TravelDistance_Mi),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / TravDistMi_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )
rm(TravDistMi_Ntile)
rm(TravDistMi_Ntile_Rows)
View(TravDistMi_Pctiles)
TravDistMi_Pctiles

Investigation of TravelDistance_Mi.

Why are some TravelDistance_Mi “NA”? It looks like partially because the records are the first trip of the day (for that bus), so I purposefully set the distance to “NA”. Another reason is due to the odometer recording a value less than the previous odometer recording. In most cases, I have no explanation for this - though I have observed about 67% of all instances where TravelDistance_Mi is NA (other than because it’s the first record of the day) are instances where DirChange2 is “Change”. This is weird and should be asked to WMATA.

Investigation of TravelDistance_Mi.

These records are NA becuase the current record odometer is less than the previous record odometer. Theoretically, this should NOT happen. Me: it appears that about 67% of all instances where TravelDistance_Mi is NA (other than because it’s th first record of the day) are instances where DirChange2 is “Change”. This is weird and should be asked to WMATA.

View(filter(AllDays_NewOrder,
            between(RowNum_OG, 194, 214) | # 204
              between(RowNum_OG, 440, 460) | # 450
              between(RowNum_OG, 478, 498) | # 488
              between(RowNum_OG, 510, 530) # 520
           )
    )
TestTable <- filter(AllDays_NewOrder,
                    BusDay_EventNum != 1
                   ) %>% 
  mutate(TravelDistance_NA = as.factor(ifelse(is.na(TravelDistance_Mi),
                                              "True",
                                              "False"
                                             )
                                      )
        ) %>%
  group_by(DirChange2, TravelDistance_NA) %>%
  summarise(TravDistMi_NACnts = n()
           )
# TestTable
TestTable_Spread <- as.data.frame(spread(TestTable,
                                         TravelDistance_NA,
                                         TravDistMi_NACnts
                                        )
                                 ) %>% 
  select(False,
         True
        )
row.names(TestTable_Spread) <- c("Change", "Same")
# str(TestTable_Spread)
# TestTable_Spread
prop.table(as.table(as.matrix(TestTable_Spread)
                   ),
           1
          )
           False      True
Change 0.8267006 0.1732994
Same   0.8884818 0.1115182
prop.table(as.table(as.matrix(TestTable_Spread)
                   ),
           2
          )
            False       True
Change 0.01948009 0.03211514
Same   0.98051991 0.96788486

Investigation of TravelDistance_Mi.

Let’s look at just the TravelDistance_Mi values that are NOT “NA”.

rm(TestTable)
rm(TestTable_Spread)
TravelDistance_Mi_NoNA <- filter(AllDays_NewOrder,
                                 # TravelDistance_Mi != 0 &
                                 !is.na(TravelDistance_Mi)
                                )
dim(AllDays_NewOrder)
[1] 2809529     120
dim(TravelDistance_Mi_NoNA)
[1] 2486795     120
nrow(AllDays_NewOrder) - nrow(TravelDistance_Mi_NoNA)
[1] 322734
str(TravelDistance_Mi_NoNA)
'data.frame':   2486795 obs. of  120 variables:
 $ RowNum_OG             : int  3 4 5 6 7 9 10 11 12 13 ...
 $ UniqueLatLng          : chr  "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" "38.766769__-77.169312" ...
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID          : chr  "5004572--5004573" "5004573--5002210" "5002210--5002209" "5002209--5000070" ...
 $ BusDay_EventNum       : int  2 3 4 5 6 7 8 9 10 11 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2            : Factor w/ 2 levels "Change","Same": 2 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 6 6 6 6 6 ...
 $ DirChange2            :

Investigation of TravelDistance_Mi.

Let’s plot just the TravelDistance_Mi values that are NOT “NA”.

TravDistMi_HistDen <- ggplot(select(TravelDistance_Mi_NoNA,
                                    TravelDistance_Mi
                                   ),
                             aes(x = TravelDistance_Mi,
                                 y = ..density..
                                )
                            ) +
  geom_histogram(binwidth = 0.05, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(0, 1.5), ylim = c(0, 4.0)
                 ) +
  labs(title = "Variation in Distance Between Stops",
       x = "Travel Distance (miles)",
       y = "Density"
      )
TravDistMi_HistDen

Investigation of TravelDistance_Mi.

Looking at the extremely large TravelDistance_Mi values. Some (aprox 27%) of TravelDistance_Mi values > 1 mile are when the DirChange2 changes…but what about the other ~73%?

Investigation of TravelDistance_Mi.

Any relation with DirChange2? Doesn’t look as if this is so.

ExtremeTravDist <- filter(AllDays_NewOrder,
                          !is.na(TravelDistance_Mi)
                         ) %>% 
  mutate(TravDist_Extreme = ifelse(TravelDistance_Mi > 1.1587121212, # 1.1587121212 is the 99th percentile
                                   "True",
                                   "False"
                                  )
                          ) %>% 
  group_by(DirChange2, TravDist_Extreme) %>% 
  summarise(TravDistMI_ExtCnts = n()
           )
# ExtremeTravDist
ExtremeTravDist_Spread <- as.data.frame(spread(ExtremeTravDist,
                                               TravDist_Extreme,
                                               TravDistMI_ExtCnts
                                              )
                                       ) %>% 
  select(False,
         True
        )
row.names(ExtremeTravDist_Spread) <- c("Change", "Same")
# str(ExtremeTravDist_Spread)
# ExtremeTravDist_Spread
prop.table(as.table(as.matrix(ExtremeTravDist_Spread)
                   ),
           1
          )
            False       True
Change 0.80622587 0.19377413
Same   0.98855456 0.01144544
prop.table(as.table(as.matrix(ExtremeTravDist_Spread)
                   ),
           2
          )
            False       True
Change 0.01594448 0.25169594
Same   0.98405552 0.74830406

Investigation of TravelDistance_Mi.

Looking at specific buses and StartStop_ID.

Investigation of TravelDistance_Mi & TravelDistance_Mi_New.

If TravelDisntace_Mi is below the 5th percentile for that StartStop_ID, or if TravelDisntace_Mi is above the 95th percentile for that StartStop_ID, or if TravelDistance_Mi is NA (when the BusDay_EventNum !=1), consider this an outlier. In this case, replace the value with the mean for that StartStop_ID and HourGroup (TD_Mi_SSHG_Mean_F), or if there are not enough values at the HourGroup level, replace it with the mean for that StartStop_ID.

# View(tail(AllDays_NewOrder, 500))
AllDays_NewTravelDist <- 
  mutate(AllDays_NewOrder,
         TravelDistance_Mi_New = ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SSHG_Cnt_F >= 20,
                                        TD_Mi_SSHG_Mean_F,
                                 ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SSHG_Cnt_F < 20 &
                                          TD_Mi_SS_Cnt_F >= 20,
                                        TD_Mi_SS_Mean_F,
                                 ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SS_Cnt_F < 20 &
                                          TD_Mi_SS_Cnt >= 20,
                                        TD_Mi_SS_Mean,
                                 ifelse(is.na(TravelDistance_Mi) &
                                          BusDay_EventNum != 1 &
                                          TravelDistance_Mi_Hvrs != 0,
                                        TravelDistance_Mi_Hvrs,
                                 ifelse(is.na(TravelDistance_Mi) &
                                          BusDay_EventNum != 1 &
                                          TravelDistance_Mi_Hvrs == 0,
                                        TD_Mi_SS_Mean,
                                        TravelDistance_Mi
                                       ))))),
         TravelDistance_Mi_New_Label = 
           factor(ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SSHG_Cnt_F >= 20,
                         "TD_Mi_SSHG_Mean_F",
                  ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SSHG_Cnt_F < 20 &
                           TD_Mi_SS_Cnt_F >= 20,
                         "TD_Mi_SS_Mean_F",
                  ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SS_Cnt_F < 20 &
                           TD_Mi_SS_Cnt >= 20,
                         "TD_Mi_SS_Mean",
                  ifelse(is.na(TravelDistance_Mi) &
                           BusDay_EventNum != 1 &
                           TravelDistance_Mi_Hvrs != 0,
                         "TravelDistance_Mi_Hvrs",
                  ifelse(is.na(TravelDistance_Mi) &
                           BusDay_EventNum != 1 &
                           TravelDistance_Mi_Hvrs == 0,
                         "TD_Mi_SS_Mean",
                         "TravelDistance_Mi"
                        )))))
                 ),
         TravelDistance_Mi_NewHvrs = ifelse(!is.na(TravelDistance_Mi_Hvrs) &
                                              TravelDistance_Mi_Hvrs != 0 &
                                              (TravelDistance_Mi_New < TD_Mi_q2 |
                                                 TravelDistance_Mi_New > TD_Mi_q98
                                              ),
                                            TravelDistance_Mi_Hvrs,
                                            TravelDistance_Mi_New
                                           ),
         TravelDistance_Mi_NewHvrs_Label =
           factor(ifelse(!is.na(TravelDistance_Mi_Hvrs) &
                           TravelDistance_Mi_Hvrs != 0 &
                           (TravelDistance_Mi_New < TD_Mi_q2 |
                              TravelDistance_Mi_New > TD_Mi_q98
                           ),
                         "TravelDistance_Mi_Hvrs",
                         as.character(TravelDistance_Mi_New_Label)
                        )
                 ),
         SpeedAvg_Mph_NewHvrs = TravelDistance_Mi_NewHvrs / TravelTime_Hr
        )
str(AllDays_NewTravelDist)
'data.frame':   2809529 obs. of  125 variables:
 $ RowNum_OG                      : int  1 3 4 5 6 7 9 10 11 12 ...
 $ UniqueLatLng                   : chr  "38.767807__-77.155136" "38.769363__-77.157082" "38.769341__-77.155136" "38.766953__-77.155113" ...
 $ group                          : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID                   : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                         : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                          : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2                     : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt                       : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2                     : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction                : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence                  : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID                       : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc                     : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean                   : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator               : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc                      : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ countryCode                    : Factor w/ 1 level "US": 1 1 1 1 1 1 1 1 1 1 ...
 $ Stop_State                     : Factor w/ 3 levels "DC","MD","VA": 3 3 3 3 3 3 3 3 3 3 ...
 $ Stop_County                    : Factor w/ 11 levels "Anne Arundel",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_City                      : Factor w/ 56 levels "Accokeek","Alexandria",..: 2 2 2 2 49 49 49 49 49 49 ...
 $ Stop_Zip                       : Factor w/ 153 levels "20001","20002",..: 150 150 150 150 123 123 123 123 123 123 ...
 $ Event_Type                     : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description              : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr                  : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth                 : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date                : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day                 : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr                  : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup             : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min                 : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time                     : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time                 : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time                     : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2                    : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time                     : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude                       : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude                      : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading                        : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance              : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1         : int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi           : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft              : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi              : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs         : num  NA 0.15 0.105 0.165 0.832 ...
 $ TD_Mi_q2                       : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98                      : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5                    : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95                   : num  NA 0.626 0.242 1.008 0.176 ...
 $ TD_Mi_SSHG_q5                  : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95                 : num  NA 0.627 0.242 0.7 0.182 ...
 $ TD_Mi_Mean                     : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F                   : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean                  : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F                : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SSHG_Mean                : num  NaN 0.442 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Mean_F              : num  NaN 0.491 0.242 0.7 0.182 ...
 $ TD_Mi_Med                      : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F                    : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med                   : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F                 : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SSHG_Med                 : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Med_F               : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_Cnt                      : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F                    : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt                   : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F                 : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TD_Mi_SSHG_Cnt                 : int  0 7 1 1 1 23 6 29 28 3 ...
 $ TD_Mi_SSHG_Cnt_F               : int  0 5 1 1 1 19 4 25 24 1 ...
 $ TravelTime_Sec                 : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_q2                      : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98                     : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5                   : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95                  : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Sec_SSHG_q5                 : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95                : num  NA 276 37 25 190 ...
 $ TT_Sec_Mean                    : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F                  : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean                 : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F               : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SSHG_Mean               : num  NaN 202 37 25 190 ...
 $ TT_Sec_SSHG_Mean_F             : num  NaN 226 37 25 190 ...
 $ TT_Sec_Med                     : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F                   : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med                  : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F                : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SSHG_Med                : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_SSHG_Med_F              : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_Cnt                     : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F                   : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt                  : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F                : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Sec_SSHG_Cnt                : int  0 7 1 1 1 35 6 36 35 3 ...
 $ TT_Sec_SSHG_Cnt_F              : int  0 5 1 1 1 31 4 32 32 1 ...
 $ TravelTime_Hr                  : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ TT_Hr_q2                       : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98                      : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5                    : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95                   : num  NA 0.0962 0.0103 0.0211 0.0525 ...
  [list output truncated]

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Quick summary and then correlation calculation.

# 38 rows meet this criteria anymore  --  appears to be the case when both the Lat Long calculations, and the TravelDistance calculations did not function properly.
View(filter(AllDays_NewTravelDist,
            is.na(TravelDistance_Mi_New) &
              BusDay_EventNum != 1
           )
    )
View(AllDays_NewTravelDist %>% 
       arrange(desc(TravelDistance_Mi_New)) %>% 
       head(500)
    )
summary(select(AllDays_NewTravelDist,
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.0     Min.   : 0.000         Min.   :  0.000      
 1st Qu.:  0.1     1st Qu.: 0.106         1st Qu.:  0.141      
 Median :  0.2     Median : 0.142         Median :  0.199      
 Mean   :  0.3     Mean   : 0.201         Mean   :  0.298      
 3rd Qu.:  0.3     3rd Qu.: 0.193         3rd Qu.:  0.276      
 Max.   :250.7     Max.   :24.407         Max.   :250.656      
 NA's   :322734    NA's   :6528           NA's   :6566         
 TravelDistance_Mi_NewHvrs
 Min.   : 0.000           
 1st Qu.: 0.142           
 Median : 0.199           
 Mean   : 0.259           
 3rd Qu.: 0.276           
 Max.   :36.236           
 NA's   :6566             
summary(select(filter(AllDays_NewTravelDist,
                      BusDay_EventNum != 1
                     ),
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.00    Min.   : 0.0000        Min.   :  0.00019    
 1st Qu.:  0.13    1st Qu.: 0.1055        1st Qu.:  0.14072    
 Median :  0.20    Median : 0.1424        Median :  0.19867    
 Mean   :  0.31    Mean   : 0.2008        Mean   :  0.29751    
 3rd Qu.:  0.29    3rd Qu.: 0.1935        3rd Qu.:  0.27633    
 Max.   :250.66    Max.   :24.4068        Max.   :250.65606    
 NA's   :316206                           NA's   :38           
 TravelDistance_Mi_NewHvrs
 Min.   : 0.00019         
 1st Qu.: 0.14205         
 Median : 0.19903         
 Mean   : 0.25859         
 3rd Qu.: 0.27557         
 Max.   :36.23636         
 NA's   :38               
cor(select(AllDays_NewTravelDist,
           TravelDistance_Mi,
           TravelDistance_Mi_Hvrs,
           TravelDistance_Mi_New,
           TravelDistance_Mi_NewHvrs
          ),
    use = "pairwise.complete.obs"
  )
                          TravelDistance_Mi TravelDistance_Mi_Hvrs
TravelDistance_Mi                 1.0000000              0.5447660
TravelDistance_Mi_Hvrs            0.5447660              1.0000000
TravelDistance_Mi_New             0.9513379              0.5837182
TravelDistance_Mi_NewHvrs         0.6005944              0.9005277
                          TravelDistance_Mi_New TravelDistance_Mi_NewHvrs
TravelDistance_Mi                     0.9513379                 0.6005944
TravelDistance_Mi_Hvrs                0.5837182                 0.9005277
TravelDistance_Mi_New                 1.0000000                 0.6346981
TravelDistance_Mi_NewHvrs             0.6346981                 1.0000000

Investigation of TravelDistance_Mi_NewHvrs_Label & TravelDistance_Mi_NewHvrs_Label.

Show how the labels changed.

group_by(AllDays_NewTravelDist,
         TravelDistance_Mi_New_Label,
         TravelDistance_Mi_NewHvrs_Label
        ) %>% 
  summarise(CntNum = n(),
            CntPct = format(CntNum / nrow(AllDays_NewTravelDist),
                            scientific = 9999
                           )
           ) %>% 
  arrange(desc(CntPct)
         )

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Graphing the two methods of calculating TravelDistance_Mi.

First, let’s get create a function to plot the liner model equation.

lm_eqn <- function(df, y, x){
  m <- lm(y ~ x, df)
  
  l <- list(a = format(coef(m)[1], digits = 2),
            b = format(abs(coef(m)[2]), digits = 2),
            s1 = ifelse(test = coef(m)[2] > 0,
                        yes = "+",
                        no = "-"
                       ),
            r2 = format(summary(m)$r.squared,
                        digits = 3
                       )
           )
  
  eq <- substitute(italic(y) == a~~s1~~b %.% italic(x)*","~~italic(r)^2~"="~r2,
                   l
                  )
  
  as.character(as.expression(eq)
              )             
}

Investigation of TravelDistance_Mi & TravelDistance_Mi_NewHvrs.

Scatter plot (using a 10% sample to making plotting time faster and to reduce un-needed data in the “same” splot).

set.seed(123456789)
AllDays_NewTravelDist_10Pct <- filter(AllDays_NewTravelDist,
                                      !is.na(TravelDistance_Mi_NewHvrs) &
                                        !is.na(TravelDistance_Mi)
                                     ) %>% 
  rename(DistMethod = TravelDistance_Mi_NewHvrs_Label) %>% 
  sample_frac(0.1)
TravDist_MiVsCalc <- ggplot(select(AllDays_NewTravelDist_10Pct,
                                   TravelDistance_Mi_NewHvrs,
                                   TravelDistance_Mi,
                                   DistMethod
                                  ),
                            aes(x = TravelDistance_Mi,
                                y = TravelDistance_Mi_NewHvrs,
                                colour = DistMethod
                               )
                           ) +
  scale_colour_manual(values = c("red","blue", "green", "orange", "black")
                     ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "blue") +
  geom_abline(intercept = 0, slope = 1, colour = "red") +
  coord_cartesian(xlim = c(0, 1.5), ylim = c(0, 1.5)
                 ) +
  scale_x_continuous(breaks = seq(0, 1.5, 0.25)
                    ) +
  scale_y_continuous(breaks = seq(0, 1.5, 0.25)
                    ) +
  theme(legend.position = "bottom", #c(0.85, 0.40),
        legend.text = element_text(size = 6)
       ) +
  annotate(label = lm_eqn(df = AllDays_NewTravelDist_10Pct,
                          x = AllDays_NewTravelDist_10Pct$TravelDistance_Mi,
                          y = AllDays_NewTravelDist_10Pct$TravelDistance_Mi_NewHvrs
                         ),
           # x = 62,
           # y = 20,
           x = 0.70,
           y = 0.00,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  annotate(label = "Reference Line (slope = 1)",
           # x = 16,
           # y = 30,
           x = 0.80,
           y = 1.05,
           geom = "text",
           size = 3,
           colour = "red"
          ) +
  labs(title = "TravelDistance_Mi vs. TravelDistance_Mi_NewHvrs",
       x = "TravelDistance_Mi",
       y = "TravelDistance_Mi_NewHvrs"
      )
# +
#   geom_jitter()
TravDist_MiVsCalc

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Graphing test with rbokeh.

TravDist_MiVsCalc_Bokeh <- figure(data = select(AllDays_NewTravelDist_10Pct,
                                                TravelDistance_Mi_NewHvrs,
                                                TravelDistance_Mi,
                                                DistMethod
                                               ),
                                  xlim = c(0, 1.5),
                                  ylim = c(0, 1.5),
                                  legend_location = "bottom_right"
                                 ) %>% 
  ly_points(x = TravelDistance_Mi,
            y = TravelDistance_Mi_NewHvrs,
            color = DistMethod,
            hover = c(TravelDistance_Mi_NewHvrs, TravelDistance_Mi, DistMethod)
           ) %>% 
  ly_abline(a = 0, b = 1, color = "red")
TravDist_MiVsCalc_Bokeh

Investigation of TravelDistance_Mi_New.

Calculating the minimum TravelDistance_Mi_New value at each percentile.

rm(TravDist_MiVsCalc_Bokeh)
rm(AllDays_NewTravelDist_10Pct)
summary(select(AllDays_NewTravelDist,
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.0     Min.   : 0.000         Min.   :  0.000      
 1st Qu.:  0.1     1st Qu.: 0.106         1st Qu.:  0.141      
 Median :  0.2     Median : 0.142         Median :  0.199      
 Mean   :  0.3     Mean   : 0.201         Mean   :  0.298      
 3rd Qu.:  0.3     3rd Qu.: 0.193         3rd Qu.:  0.276      
 Max.   :250.7     Max.   :24.407         Max.   :250.656      
 NA's   :322734    NA's   :6528           NA's   :6566         
 TravelDistance_Mi_NewHvrs
 Min.   : 0.000           
 1st Qu.: 0.142           
 Median : 0.199           
 Mean   : 0.259           
 3rd Qu.: 0.276           
 Max.   :36.236           
 NA's   :6566             
summary(select(filter(AllDays_NewTravelDist,
                      BusDay_EventNum != 1
                     ),
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.00    Min.   : 0.0000        Min.   :  0.00019    
 1st Qu.:  0.13    1st Qu.: 0.1055        1st Qu.:  0.14072    
 Median :  0.20    Median : 0.1424        Median :  0.19867    
 Mean   :  0.31    Mean   : 0.2008        Mean   :  0.29751    
 3rd Qu.:  0.29    3rd Qu.: 0.1935        3rd Qu.:  0.27633    
 Max.   :250.66    Max.   :24.4068        Max.   :250.65606    
 NA's   :316206                           NA's   :38           
 TravelDistance_Mi_NewHvrs
 Min.   : 0.00019         
 1st Qu.: 0.14205         
 Median : 0.19903         
 Mean   : 0.25859         
 3rd Qu.: 0.27557         
 Max.   :36.23636         
 NA's   :38               
TravDistMiN_Ntile <- as.data.frame(select(AllDays_NewTravelDist,
                                          StartStop_ID,
                                          TravelDistance_Mi_New_Label,
                                          # TravelDistance_Mi_NewHvrs_Label,
                                          TravelDistance_Mi_New
                                          # TravelDistance_Mi_NewHvrs
                                         )
                                  ) %>% 
  mutate(PctR_N = percent_rank(AllDays_NewTravelDist$TravelDistance_Mi_New),
         # PctR_H = percent_rank(AllDays_NewTravelDist$TravelDistance_Mi_NewHvrs),
         PctR_Round_N = round(PctR_N, 2)
         # PctR_Round_H = round(PctR_H, 2)
        ) 
# str(TravDistMiN_Ntile)
# View(head(TravDistMiN_Ntile, 500))
TravDistMiN_Ntile_Rows <- nrow(TravDistMiN_Ntile)
# View(tail(TravDistMiN_Ntile, 500))
TravDistMiN_Pctiles <- group_by(TravDistMiN_Ntile,
                                PctR_Round_N
                               ) %>% 
  summarise(
    MinTDMiAtPctile_N = min(TravelDistance_Mi_New),
    # MinTDMiAtPctile_H = min(TravelDistance_Mi_NewHvrs),
    CntsAtPctile_N = sum(!is.na(TravelDistance_Mi_New)),
    # CntsAtPctile_H = sum(!is.na(TravelDistance_Mi_NewHvrs)),
    PctsAtPctile_N = CntsAtPctile_N / TravDistMiN_Ntile_Rows
    # PctsAtPctile_H = CntsAtPctile_H / TravDistMiN_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP_N = cumsum(PctsAtPctile_N)
         # CumSumPAtP_H = cumsum(PctsAtPctile_H)
        )
# View(TravDistMiN_Pctiles)

Investigation of TravelDistance_Mi_NewHvrs

Calculating the minimum TravelDistance_Mi_NewHvrs value at each percentile.

Join TravDistMiH_Pctiles, TravDistMiN_Pctiles, and TravDistMi_Pctiles.

~11% of rides are still showing as less than 0.1 miles of TravelDistance_Mi_NewHvrs.

Investigation of TravelDistance_Mi_New.

Why are there still some small or large TravelDistance_Mi_NewHvrs values.

Investigation of TravelTime_Hr.

View(TravDistMi_Pctiles): 98% of TravelTime_Hr are between 7 seconds and 464 seconds (~8 minutes).

Investigation of TravelTime_Hr.

Histogram of TravelTime_Sec.

TravTime_Sec_HistDen <- ggplot(filter(select(AllDays_NewTravelDist,
                                             TravelTime_Sec
                                            ),
                                      !is.na(TravelTime_Sec)
                                     ),
                               aes(x = TravelTime_Sec,
                                   y = ..density..
                                  )
                          ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  # stat_bin(binwidth = 5,
  #          geom = "text",
  #          size = 2.5,
  #          vjust = 1.5,
  #          aes(label = format(..count.., big.mark = ",")
  #             ),
  #         ) +
  coord_cartesian(xlim = c(0, 180), ylim = c(0, 0.02)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Time",
       x = "Travel Time (sec)",
       y = "Density"
      )
TravTime_Sec_HistDen

Investigation of TravelTime_Sec.

TravelTime_Sec values are NA.

summary(AllDays_NewTravelDist$TravelTime_Sec)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
    1.0    25.0    39.0   104.9    72.0 60750.0    6641 
View(select(AllDays_NewTravelDist,
            -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
           ) %>% 
       filter(is.na(TravelTime_Sec) &
                BusDay_EventNum != 1  # TravelTime purposefully not calculated here
             )
    )
# examples of TravelTime_Sec values that are NA. These are NA because the Event_Time & Departure_Time readings are not accurate (i.e., the previous Departure_Time is BEFORE or EQUAL TO the current Event_Time).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 90809 & RowNum_OG <= 90829) | # 90819
                (RowNum_OG >= 90881 & RowNum_OG <= 90901) | # 90891
                (RowNum_OG >= 2597066 & RowNum_OG <= 2597086) | # 2597076
                (RowNum_OG >= 2613305 & RowNum_OG <= 2613325) # 2613315
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt"))
    )

Investigation of TravelTime_Sec.

TravelTime_Sec values are extremely small.

Investigation of TravelTime_Sec.

TravelTime_Sec values are extremely large.

Investigation of TravelTime_Sec.

Are large TravelTime_Sec values related to RouteChanges? Looks likely. When the Bus involves a Route “change”, there is almost twice as likely to be a case of an outlier TravelTime_Sec value (on the high side).

prop.table(as.table(as.matrix(TTLargeRteChng_Spread)
                   ),
           1
          )
             Normal      Outlier         <NA>
Change 2.583712e-01 4.669780e-01 2.746508e-01
Same   9.889061e-01 1.105373e-02 4.020451e-05
prop.table(as.table(as.matrix(TTLargeRteChng_Spread)
                   ),
           2
          )
            Normal     Outlier        <NA>
Change 0.002224561 0.264978279 0.983135070
Same   0.997775439 0.735021721 0.016864930

Investigation of TravelTime_Sec.

If TravelTime_Sec is below the 5th percentile for that StartStop_ID, or if TravelTime_Sec is above the 95th percentile for that StartStop_ID, consider this an outlier. In this case, replace the value with the mean for that StartStop_ID and HourGroup (TT_Sec_SSHG_Mean_F), or if there are not enough values at the HourGroup level, replace it with the mean for that StartStop_ID.

NewTravTime <- mutate(AllDays_NewTravelDist,
                      TT_Sec_New = ifelse(!is.na(TravelTime_Sec) &
                                            (TravelTime_Sec < TT_Sec_SSHG_q5 |
                                               TravelTime_Sec > TT_Sec_SSHG_q95
                                            ) &
                                            TT_Sec_SSHG_Cnt_F >= 20,
                                          TT_Sec_SSHG_Mean_F,
                                   ifelse(!is.na(TravelTime_Sec) &
                                            (TravelTime_Sec < TT_Sec_SSHG_q5 |
                                               TravelTime_Sec > TT_Sec_SSHG_q95
                                            ) &
                                            TT_Sec_SSHG_Cnt_F < 20 &
                                            TT_Sec_SS_Cnt_F >= 20,
                                          TT_Sec_SS_Mean_F,
                                   ifelse(!is.na(TravelTime_Sec) &
                                            (TravelTime_Sec < TT_Sec_SSHG_q5 |
                                               TravelTime_Sec > TT_Sec_SSHG_q95
                                            ) &
                                            TT_Sec_SS_Cnt_F < 20 &
                                            TT_Sec_SS_Cnt >= 20,
                                          TT_Sec_SS_Mean,
                                   ifelse(!is.na(TravelTime_Sec) &
                                            (TravelTime_Sec < TT_Sec_SSHG_q5 |
                                               TravelTime_Sec > TT_Sec_SSHG_q95
                                            ) &
                                            TT_Sec_SS_Cnt_F < 20 &
                                            TT_Sec_SS_Cnt < 20 &
                                            RteChange2 == "Change",
                                          NA,
                                          TravelTime_Sec
                                         )))),
                      
                      TT_Sec_New_Label = 
           factor(ifelse(!is.na(TravelTime_Sec) &
                           (TravelTime_Sec < TT_Sec_SSHG_q5 |
                              TravelTime_Sec > TT_Sec_SSHG_q95
                           ) &
                           TT_Sec_SSHG_Cnt_F >= 20,
                         "TT_Sec_SSHG_Mean_F",
                  ifelse(!is.na(TravelTime_Sec) &
                           (TravelTime_Sec < TT_Sec_SSHG_q5 |
                              TravelTime_Sec > TT_Sec_SSHG_q95
                           ) &
                           TT_Sec_SSHG_Cnt_F < 20 &
                           TT_Sec_SS_Cnt_F >= 20,
                         "TT_Sec_SS_Mean_F",
                  ifelse(!is.na(TravelTime_Sec) &
                           (TravelTime_Sec < TT_Sec_SSHG_q5 |
                              TravelTime_Sec > TT_Sec_SSHG_q95
                            ) &
                           TT_Sec_SS_Cnt_F < 20 &
                           TT_Sec_SS_Cnt >= 20,
                         "TT_Sec_SS_Mean",
                  ifelse(!is.na(TravelTime_Sec) &
                           (TravelTime_Sec < TT_Sec_SSHG_q5 |
                              TravelTime_Sec > TT_Sec_SSHG_q95
                           ) &
                           TT_Sec_SS_Cnt_F < 20 &
                           TT_Sec_SS_Cnt < 20 &
                           RteChange2 == "Change",
                         NA,
                         "TravelTime_Sec"
                        ))))
                 ),
                  
                  TT_Hr_New = TT_Sec_New / (60 * 60)
           )
dim(AllDays_NewTravelDist)
[1] 2809529     125
dim(NewTravTime)
[1] 2809529     128
rm(AllDays_NewTravelDist)
summary(select(NewTravTime,
           -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
          )
   )
   RowNum_OG       UniqueLatLng       group      StartStop_ID      
 Min.   :      1   Length:2809529     1:559521   Length:2809529    
 1st Qu.: 784722   Class :character   2:561389   Class :character  
 Median :1563300   Mode  :character   3:567794   Mode  :character  
 Mean   :1562504                      4:559180                     
 3rd Qu.:2337981                      5:561645                     
 Max.   :3119443                                                   
                                                                   
 BusDay_EventNum      Bus_ID        Route            RteChange2     
 Min.   :   1.0   Min.   :  11   Length:2809529     Change:  23772  
 1st Qu.: 113.0   1st Qu.:2922   Class :character   Same  :2785757  
 Median : 248.0   Median :6195   Mode  :character                   
 Mean   : 290.5   Mean   :5382                                      
 3rd Qu.: 428.0   3rd Qu.:7104                                      
 Max.   :1344.0   Max.   :8105                                      
                                                                    
    RouteAlt        DirChange2      Route_Direction   Stop_Sequence   
 2      :1128810   Change:  65126   SOUTH   :739235   Min.   :  1.00  
 1      :1065425   Same  :2744403   NORTH   :735203   1st Qu.: 12.00  
 3      : 260372                    WEST    :649706   Median : 24.00  
 4      : 130801                    EAST    :628074   Mean   : 26.83  
 5      :  75039                    LOOP    : 35611   3rd Qu.: 39.00  
 6      :  56408                    CLOCKWIS: 10671   Max.   :104.00  
 (Other):  92674                    (Other) : 11029                   
   Start_ID          Start_Desc        StopID_Clean       StopID_Indicator
 Length:2809529     Length:2809529     Length:2809529     ID_Bad:  18948  
 Class :character   Class :character   Class :character   ID_OK :2790581  
 Mode  :character   Mode  :character   Mode  :character                   
                                                                          
                                                                          
                                                                          
                                                                          
  Stop_Desc         countryCode    Stop_State                   Stop_County     
 Length:2809529     US  :2808431   DC  :1297006   District of Columbia:1297006  
 Class :character   NA's:   1098   MD  : 982401   Prince George's     : 589193  
 Mode  :character                  VA  : 529024   Montgomery          : 391422  
                                   NA's:   1098   Fairfax             : 204558  
                                                  Arlington           : 198618  
                                                  (Other)             : 127634  
                                                  NA's                :   1098  
         Stop_City          Stop_Zip         Event_Type 
 Washington   :1296626   20020  : 156333   Min.   :3.0  
 Silver Spring: 227570   20032  : 117215   1st Qu.:3.0  
 Arlington    : 198360   20019  : 116560   Median :4.0  
 Hyattsville  : 166930   20011  : 114518   Mean   :3.6  
 Alexandria   : 103776   20002  : 101086   3rd Qu.:4.0  
 (Other)      : 815169   (Other):2202719   Max.   :5.0  
 NA's         :   1098   NA's   :   1098                
                                          Event_Description   Event_Time_Yr 
 Serviced Stop                                     :1127366   Min.   :2016  
 Unknown Stop                                      :   2579   1st Qu.:2016  
 UnServiced Stop                                   :1679584   Median :2016  
                                                              Mean   :2016  
                                                              3rd Qu.:2016  
                                                              Max.   :2016  
                                                                            
 Event_Time_Mth Event_Time_Date Event_Time_Day Event_Time_Hr    Event_Time_HrGroup
 Min.   :10     Min.   :3.000   Sun  :     0   Min.   : 0.00   Group6_8  :611612  
 1st Qu.:10     1st Qu.:4.000   Mon  :559521   1st Qu.: 8.00   Group15_17:560103  
 Median :10     Median :5.000   Tues :561389   Median :13.00   Group18_20:461056  
 Mean   :10     Mean   :5.001   Wed  :567794   Mean   :12.97   Group9_11 :396514  
 3rd Qu.:10     3rd Qu.:6.000   Thurs:559180   3rd Qu.:18.00   Group12_14:353603  
 Max.   :10     Max.   :7.000   Fri  :561645   Max.   :23.00   Group21_23:244522  
                                Sat  :     0                   (Other)   :182119  
 Event_Time_Min    Event_Time                  Departure_Time               
 Min.   : 0.00   Min.   :2016-10-03 00:00:00   Min.   :2016-10-03 00:00:00  
 1st Qu.:14.00   1st Qu.:2016-10-04 08:36:14   1st Qu.:2016-10-04 08:36:20  
 Median :29.00   Median :2016-10-05 13:49:29   Median :2016-10-05 13:49:38  
 Mean   :29.43   Mean   :2016-10-05 13:29:21   Mean   :2016-10-05 13:29:28  
 3rd Qu.:44.00   3rd Qu.:2016-10-06 17:58:06   3rd Qu.:2016-10-06 17:58:13  
 Max.   :59.00   Max.   :2016-10-07 23:59:59   Max.   :2016-10-08 00:12:31  
                                                                            
   Dwell_Time       Dwell_Time2         Delta_Time         Latitude    
 Min.   :   0.00   Min.   :   0.000   Min.   :-5606.0   Min.   : 0.00  
 1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   14.0   1st Qu.:38.86  
 Median :   0.00   Median :   0.000   Median :  157.0   Median :38.90  
 Mean   :  12.56   Mean   :   6.359   Mean   :  268.8   Mean   :38.91  
 3rd Qu.:   5.00   3rd Qu.:   4.000   3rd Qu.:  396.0   3rd Qu.:38.96  
 Max.   :6205.00   Max.   :6205.000   Max.   : 9426.0   Max.   :39.19  
                                                                       
   Longitude         Heading      Odometer_Distance  Odometer_Distance_Lag1
 Min.   :-77.45   Min.   :  0.0   Min.   :       0   Min.   :       0      
 1st Qu.:-77.07   1st Qu.: 89.0   1st Qu.:  177595   1st Qu.:  177326      
 Median :-77.02   Median :180.0   Median :  377510   Median :  376934      
 Mean   :-77.02   Mean   :176.9   Mean   :  426254   Mean   :  425713      
 3rd Qu.:-76.97   3rd Qu.:269.0   3rd Qu.:  623667   3rd Qu.:  622879      
 Max.   :  0.00   Max.   :360.0   Max.   :11108034   Max.   :10853226      
                                                     NA's   :6528          
 Odometer_Distance_Mi TravelDistance_Ft TravelDistance_Mi TravelDistance_Mi_Hvrs
 Min.   :   0.00      Min.   :      1   Min.   :  0.0     Min.   : 0.000        
 1st Qu.:  33.64      1st Qu.:    699   1st Qu.:  0.1     1st Qu.: 0.106        
 Median :  71.50      Median :   1044   Median :  0.2     Median : 0.142        
 Mean   :  80.73      Mean   :   1624   Mean   :  0.3     Mean   : 0.201        
 3rd Qu.: 118.12      3rd Qu.:   1518   3rd Qu.:  0.3     3rd Qu.: 0.193        
 Max.   :2103.79      Max.   :1323464   Max.   :250.7     Max.   :24.407        
                      NA's   :322734    NA's   :322734    NA's   :6528          
 TravelTime_Sec    TravelTime_Hr     SpeedAvg_Mph     TravelDistance_Mi_New
 Min.   :    1.0   Min.   : 0.000   Min.   :    0.0   Min.   :  0.000      
 1st Qu.:   25.0   1st Qu.: 0.007   1st Qu.:   10.1   1st Qu.:  0.141      
 Median :   39.0   Median : 0.011   Median :   16.7   Median :  0.199      
 Mean   :  104.9   Mean   : 0.029   Mean   :   26.5   Mean   :  0.298      
 3rd Qu.:   72.0   3rd Qu.: 0.020   3rd Qu.:   31.2   3rd Qu.:  0.276      
 Max.   :60750.0   Max.   :16.875   Max.   :22924.1   Max.   :250.656      
 NA's   :6641      NA's   :6641     NA's   :322762    NA's   :6566         
         TravelDistance_Mi_New_Label TravelDistance_Mi_NewHvrs
 TD_Mi_SS_Mean         :   1425      Min.   : 0.000           
 TD_Mi_SS_Mean_F       :  68790      1st Qu.: 0.142           
 TD_Mi_SSHG_Mean_F     : 235643      Median : 0.199           
 TravelDistance_Mi     :2187829      Mean   : 0.259           
 TravelDistance_Mi_Hvrs: 315842      3rd Qu.: 0.276           
                                     Max.   :36.236           
                                     NA's   :6566             
       TravelDistance_Mi_NewHvrs_Label SpeedAvg_Mph_NewHvrs   TT_Sec_New      
 TD_Mi_SS_Mean         :   1258        Min.   :   0.00      Min.   :    1.00  
 TD_Mi_SS_Mean_F       :  67174        1st Qu.:  10.09      1st Qu.:   25.00  
 TD_Mi_SSHG_Mean_F     : 232871        Median :  16.60      Median :   39.00  
 TravelDistance_Mi     :2122413        Mean   :  24.11      Mean   :   91.31  
 TravelDistance_Mi_Hvrs: 385813        3rd Qu.:  28.83      3rd Qu.:   70.00  
                                       Max.   :8691.73      Max.   :60750.00  
                                       NA's   :6667         NA's   :9218      
           TT_Sec_New_Label     TT_Hr_New     
 TravelTime_Sec    :2503794   Min.   : 0.000  
 TT_Sec_SS_Mean    :    804   1st Qu.: 0.007  
 TT_Sec_SS_Mean_F  :  52426   Median : 0.011  
 TT_Sec_SSHG_Mean_F: 249928   Mean   : 0.025  
 NA's              :   2577   3rd Qu.: 0.019  
                              Max.   :16.875  
                              NA's   :9218    
str(select(NewTravTime,
           TravelTime_Sec,
           TT_Sec_New,
           TT_Sec_New_Label,
           TT_Hr_New
          )
   )
'data.frame':   2809529 obs. of  4 variables:
 $ TravelTime_Sec  : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_New      : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_New_Label: Factor w/ 4 levels "TravelTime_Sec",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ TT_Hr_New       : num  NA 0.05 0.01028 0.00694 0.05278 ...
summary(select(NewTravTime,
               TravelTime_Sec,
               TT_Sec_New,
               TT_Sec_New_Label,
               TT_Hr_New
              )
       )
 TravelTime_Sec      TT_Sec_New                 TT_Sec_New_Label     TT_Hr_New     
 Min.   :    1.0   Min.   :    1.00   TravelTime_Sec    :2503794   Min.   : 0.000  
 1st Qu.:   25.0   1st Qu.:   25.00   TT_Sec_SS_Mean    :    804   1st Qu.: 0.007  
 Median :   39.0   Median :   39.00   TT_Sec_SS_Mean_F  :  52426   Median : 0.011  
 Mean   :  104.9   Mean   :   91.31   TT_Sec_SSHG_Mean_F: 249928   Mean   : 0.025  
 3rd Qu.:   72.0   3rd Qu.:   70.00   NA's              :   2577   3rd Qu.: 0.019  
 Max.   :60750.0   Max.   :60750.00                                Max.   :16.875  
 NA's   :6641      NA's   :9218                                    NA's   :9218    

Test investigation of just the X2 Route (box plots).

Test investigation of just the X2 Route (violin plots).

TimeBtwEvents_X2_ViolinPlot <- ggplot(select(as.data.frame(X2_ByStop),
                                             TimeToEvent_Min,
                                             Event_Time_HrGroup
                                             ),
                                      aes(factor(Event_Time_HrGroup),
                                          TimeToEvent_Min,
                                          fill = factor(Event_Time_HrGroup)
                                         )
                                     ) + 
  geom_violin(draw_quantiles = c(0.25, 0.5, 0.75),
              trim = TRUE,
              scale = "count",
              na.rm = TRUE,
              show.legend = NA,
              inherit.aes = TRUE
             ) +
  geom_text(data = Count_Values,
            aes(y = Value_Counts,
                label = format(round(Value_Counts, digits = 1),
                               nsmall = 1
                              )
               ),
            size = 2.5,
            vjust = -0.5
           ) +
  theme(legend.position="none", axis.text.x = element_text(angle=45)) +
  coord_cartesian(# xlim = c(0, 180),
                  ylim = c(0, 80)
                 ) +
  labs(title = "How Often an X2 Arrives at a Given Stop",
       x = "Hour Group",
       y = "Time Between Busses (min)"
      )
TimeBtwEvents_X2_ViolinPlot

Investigating TravelTime_Sec.


View(filter(TTLargeRteChng,
            !is.na(TravelTime_Sec) &
              RteChange2 == "Same"
           ) %>% 
       arrange(desc(TravelTime_Sec),
               SpeedAvg_Mph_NewHvrs
              ) %>%
       head(500)
    )


# examples where TravelTime_Sec is small (1 sec) and SpeedAvg_Mph_NewHvrs is large.
View(select(NewTravTime,
            # -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
            -(TD_Mi_q2:TD_Mi_SSHG_Cnt_F),
            -(TT_Hr_q2:TT_Hr_SSHG_Cnt_F)
           ) %>% 
       filter((RowNum_OG >= 2217353 & RowNum_OG <= 2217373) | # 2217363
                (RowNum_OG >= 3090321 & RowNum_OG <= 3090341) | # 3090331
                (RowNum_OG >= 80764 & RowNum_OG <= 80784) | # 80774
                (RowNum_OG >= 33840 & RowNum_OG <= 33860) # 33850
           )
    )






# examples where TravelTime_Sec is large and SpeedAvg_Mph_NewHvrs is small.
View(filter(TTLargeRteChng,
            (RowNum_OG >= 2250290 & RowNum_OG <= 2250310) | # 2250300
              (RowNum_OG >= 867717 & RowNum_OG <= 867737) | # 867727
              (RowNum_OG >= 864379 & RowNum_OG <= 864399) | # 864389
              (RowNum_OG >= 808395 & RowNum_OG <= 808415) # 808405
           )
    )

         
         
# examples where TravelTime_Sec is unusually small (with TravelDistance_Mi values that are large).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 1042228 & RowNum_OG <= 1042248) | # 1042238
                (RowNum_OG >= 53816 & RowNum_OG <= 53836) | # 53826
                (RowNum_OG >= 360571 & RowNum_OG <= 360591) | # 360581
                (RowNum_OG >= 502271 & RowNum_OG <= 502291) # 502281 (can't explian the weird TravelTime_Sec calculation here - it's not even an integer!)
           )
    )

# still trying to explain 502281...on the day of this weirdness, the bus was only in circulation for 4-5 stops (~20 minutes) on that day (Oct 6)
View(filter(AllDays_NewTravelDist,
            Bus_ID == 2711
           )
    )


# exploring large values for TravelTime_Sec
View(filter(AllDays_NewTravelDist,
            TravelTime_Sec == 300
           ) %>% 
       arrange(desc(TravelTime_Sec),
               SpeedAvg_Mph2
              )
    )

# examples where TravelTime_Sec is unusually large (with TravelDistance_Mi values that are small, so SpeedAvg_Mph values are very small).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 2627459 & RowNum_OG <= 2627479) | # 2627469
                (RowNum_OG >= 2193344 & RowNum_OG <= 2193364) | # 2193354
                (RowNum_OG >= 1644123 & RowNum_OG <= 1644143) | # 1644133
                (RowNum_OG >= 869600 & RowNum_OG <= 869620) # 869610
           )
    )

Investigation of SpeedAvg_Mph2

View(Speed_Pctiles): 90% of SpeedAvg_Mph2 are between ~3mph and ~66mph.


Speed_Ntile <- as.data.frame(AllDays_NewTravelDist$SpeedAvg_Mph2) %>% 
  mutate(Pctile = ntile(AllDays_NewTravelDist$SpeedAvg_Mph2, 100),
         MinR = min_rank(AllDays_NewTravelDist$SpeedAvg_Mph2),
         PctR = percent_rank(AllDays_NewTravelDist$SpeedAvg_Mph2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(Speed_Ntile)[1] <- "SpeedAvg_Mph2"
str(Speed_Ntile)

Speed_Ntile_Rows <- nrow(Speed_Ntile)

View(tail(Speed_Ntile, 500))


Speed_Pctiles <- group_by(Speed_Ntile,
                          PctR_Round
                         ) %>% 
  summarise(
    MinSpeedAtPctile = min(SpeedAvg_Mph2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / Speed_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(Speed_Pctiles)

Investigation of SpeedAvg_Mph2.

Exploring the removal of outlier TravelTime_Sec and TravelDistance_Mi.


summary(select(AllDays_NewTravelDist,
               SpeedAvg_Mph,
               SpeedAvg_Mph2
              )
       )

summary(select(filter(AllDays_NewTravelDist,
                      TravelDistance_Mi > 0.0001893939 & # lowest non-zero percentile
                        TravelDistance_Mi < 1.0812500000 & # 99th percentile
                        TravelTime_Sec > 10.050000 & # 2nd percentile
                        TravelTime_Sec < 293.000000 # 98th percentile
                     ),
               SpeedAvg_Mph,
               SpeedAvg_Mph2
              )
       )

Investigation of SpeedAvg_Mph2.

Histogram of SpeedAvg_Mph2.


Speed_HistDen <- ggplot(filter(AllDays_NewTravelDist,
                               !is.na(SpeedAvg_Mph2)
                              ),
                        aes(x = SpeedAvg_Mph2,
                            y = ..density..
                           )
                       ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  stat_bin(binwidth = 5,
           geom = "text",
           size = 2.5,
           vjust = 1.5,
           aes(label = format(..count.., big.mark = ",")
              ),
          ) +
  # geom_text(aes(label = format(..count.., big.mark = ",")
  #              ),
  #           size = 3,
  #           nudge_y = (..count.. * 0.1)
  #          ) +
  coord_cartesian(xlim = c(0, 70), ylim = c(0, 0.04)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Speed",
       x = "Average Speed (mph)",
       y = "Density"
      )

Speed_HistDen

Investigation of SpeedAvg_Mph2.

Histogram of SpeedAvg_Mph2 after removing outlier TravelTime_Sec and TravelDistance_Mi.


View(TravDistMiNew_Pctiles)
View(TravTimeHr_Pctiles)

SpeedNoOutlier_HistDen <- ggplot(filter(AllDays_NewTravelDist,
                                        !is.na(SpeedAvg_Mph2) &
                                          TravelDistance_Mi_New > 0.077841005 & # 5th percentile
                                          # TravelDistance_Mi_New < 1.0812500000 & # 99th percentile
                                          TravelTime_Sec > 12.100000 # 4th percentile
                                          # TravelTime_Sec < 293.000000 # 98th percentile
                                       ),
                                 aes(x = SpeedAvg_Mph2,
                                     y = ..density..
                                    )
                                ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  stat_bin(binwidth = 5,
           geom = "text",
           size = 2.5,
           vjust = 1.5,
           aes(label = format(..count.., big.mark = ",")
              ),
          ) +
  # geom_text(aes(label = format(..count.., big.mark = ",")
  #              ),
  #           size = 3,
  #           nudge_y = (..count.. * 0.1)
  #          ) +
  coord_cartesian(xlim = c(0, 70), ylim = c(0, 0.04)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Speed",
       subtitle = "(removed low outliers of Travel Distance and Travel Time)",
       x = "Average Speed (mph)",
       y = "Density"
      )

SpeedNoOutlier_HistDen

Investigation of SpeedAvg_Mph2.

New dataset (NoOutliers_TravelDistNTime) when removing outlier low values of TravelDistance_Mi_New and TravelTime_Sec.


View(TravDistMiNew_Pctiles)
View(TravTimeHr_Pctiles)

NoOutliers_TravelDistNTime <- filter(AllDays_NewTravelDist,
                                     TravelDistance_Mi_New > .077841005 & # 5th percentile
                                       # TravelDistance_Mi_New < 1.0812500000 & # 99th percentile
                                       TravelTime_Sec > 12.100000 # 4th percentile
                                       # TravelTime_Sec < 293.000000 # 98th percentile
                                    )

nrow(AllDays_NewTravelDist) - nrow(NoOutliers_TravelDistNTime)

str(NoOutliers_TravelDistNTime)
summary(NoOutliers_TravelDistNTime)

Investigation of SppedAvg_Mph2.

View(Speed_NoOut_Pctiles): Aproximately 90% of SpeedAvg_Mph2 values are between ~4mph and ~56mph.


Speed_NoOut_Ntile <- as.data.frame(NoOutliers_TravelDistNTime$SpeedAvg_Mph2) %>% 
  mutate(Pctile = ntile(NoOutliers_TravelDistNTime$SpeedAvg_Mph2, 100),
         MinR = min_rank(NoOutliers_TravelDistNTime$SpeedAvg_Mph2),
         PctR = percent_rank(NoOutliers_TravelDistNTime$SpeedAvg_Mph2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(Speed_NoOut_Ntile)[1] <- "SpeedAvg_Mph2"
str(Speed_NoOut_Ntile)

Speed_NoOut_Ntile_Rows <- nrow(Speed_NoOut_Ntile)

View(tail(Speed_NoOut_Ntile, 500))


Speed_NoOut_Pctiles <- group_by(Speed_NoOut_Ntile,
                                PctR_Round
                               ) %>% 
  summarise(
    MinSpeedAtPctile = min(SpeedAvg_Mph2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / Speed_NoOut_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(Speed_NoOut_Pctiles)

Investigation of SppedAvg_Mph2.

Exloring odd/impossible values.


# Exploring when SpeedAvg_Mph2 is NA  --  does not occur at all
nrow(filter(NoOutliers_TravelDistNTime,
            is.na(SpeedAvg_Mph2)
           )
    )


# Exploring when SpeedAvg_Mph2 is zero  --  does not occur at all
nrow(filter(NoOutliers_TravelDistNTime,
            SpeedAvg_Mph2 == 0
           )
    )


# examples where SpeedAvg_Mph2 < 3.2848770
View(filter(AllDays_NewTravelDist,
            SpeedAvg_Mph2 > 0 &
              SpeedAvg_Mph2 < 3.2848770
           ) %>% 
       arrange(SpeedAvg_Mph2)
    )

# examples where SpeedAvg_Mph2 < 3.2848770
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 485338 & RowNum_OG <= 485358) | # 485348  --  Extreme travel time, Route Change
                (RowNum_OG >= 346952 & RowNum_OG <= 346972) | # 346962  -- Extreme travel time, Route Change 
                (RowNum_OG >= 70494 & RowNum_OG <= 70514) | # 70504  --  Extreme travel time, Route Change
                (RowNum_OG >= 2051846 & RowNum_OG <= 2051866) # 2051856  --  Extreme travel time, Route Change
           )
    )

Investigation of SpeedAvg_Mph2.

Limit the dataset based on SpeedAvg_Mph2.


NoOutliersSpeed <- filter(NoOutliers_TravelDistNTime,
                          between(SpeedAvg_Mph2,
                                  4.069300, # 5th percentile
                                  56.05651 #95th percentile
                                 )
                          )

nrow(NoOutliers_TravelDistNTime) - nrow(NoOutliersSpeed)

summary(NoOutliersSpeed)

TravelTime now looks like it has some odd values on the high end. So let’s look at those.

View(TravTime_NoOut_Pctiles): Virtually all trips should take less than 5 minutes. (The 99th percentile of of TravelTime is approximately 8 minutes.)


TravTime_NoOut_Ntile <- as.data.frame(NoOutliersSpeed$TravelTime_Hr) %>% 
  mutate(Pctile = ntile(NoOutliersSpeed$TravelTime_Hr, 100),
         MinR = min_rank(NoOutliersSpeed$TravelTime_Hr),
         PctR = percent_rank(NoOutliersSpeed$TravelTime_Hr),
         PctR_Round = round(PctR, 2)
        )

colnames(TravTime_NoOut_Ntile)[1] <- "TravelTime_Hr"
str(TravTime_NoOut_Ntile)

TravTime_NoOut_Ntile_Rows <- nrow(TravTime_NoOut_Ntile)

View(tail(TravTime_NoOut_Ntile, 500))


TravTime_NoOut_Pctiles <- group_by(TravTime_NoOut_Ntile,
                                   PctR_Round
                                  ) %>% 
  summarise(
    MinTravTimeHrAtPctile = min(TravelTime_Hr),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / TravTime_NoOut_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile),
         MinTravTimeSecAtPctile = MinTravTimeHrAtPctile * (60 * 60)
        )

View(TravTime_NoOut_Pctiles)

Investigating odd TravelTime_Sec values.

Trips longer than ~8 minutes.


View(filter(NoOutliersSpeed,
            TravelTime_Sec > 491 # min at the 100th percentile
           ) %>% 
       arrange(desc(TravelTime_Sec)
              )
    )

# examples of TravelTime_Sec values that are largest.
View(filter(NoOutliersSpeed,
            (RowNum_OG >= 2071759 & RowNum_OG <= 2071779) | # 2071769  --  results from a route change, and a 3hr+ wait before the new route starts
                (RowNum_OG >= 1473686 & RowNum_OG <= 1473706) | # 1473696  --  results from a route change, and a 3hr wait before the new route starts
                (RowNum_OG >= 1222822 & RowNum_OG <= 1222842) | # 1222832  --  results from a route change, and a 3hr wait before the new route starts
                (RowNum_OG >= 3046089 & RowNum_OG <= 3046109) # 3046099  --  results from a route change, and a 3hr wait before the new route starts
           )
    )


# examples of TravelTime_Sec values that are the smallest of the large.
View(filter(NoOutliersSpeed,
            (RowNum_OG >= 3044689 & RowNum_OG <= 3044709) | # 3044699  --  results from a route change
                (RowNum_OG >= 3022358 & RowNum_OG <= 3022378) | # 3022368  --  results from a route change
                (RowNum_OG >= 2993016 & RowNum_OG <= 2993036) | # 2993026  --  results from a previous route change (change occurred in deleted row)
                (RowNum_OG >= 2683703 & RowNum_OG <= 2683723) # 2683713  --  results from a previous route change (change occurred in deleted row)
           )
    )

Let’s look at the TravelTime_Sec values and route changes (DirChange2).

The 99th percentile of TravelTime_Sec for both, all trips, and just those trips NOT involving route changes (DirChange2 = “Same”), is approximately 5min (300 sec).

Nota Bene: The percentile calculation here is defined slightly different than in most of the above analyses (which get the lowest value in the bin created by 100 ntiles).


summary(select(NoOutliersSpeed,
               TravelTime_Sec
              )
       )

summary(select(filter(NoOutliersSpeed,
                      DirChange2 == "Same"
                     ),
               TravelTime_Sec
              )
       )

summary(select(filter(NoOutliersSpeed,
                      DirChange2 == "Change"
                     ),
               TravelTime_Sec
              )
       )


TravTimeSec_Qtiles_df <- data.frame(PctValue = seq(0, 100, 1),
                                    All = seq(1, 101, 1),
                                    Same = seq(1, 101, 1),
                                    Change = seq(1, 101, 1)
                                   )

TravTimeSec_Qtiles_df[ , 2] <- quantile(select(NoOutliersSpeed,
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

TravTimeSec_Qtiles_df[ , 3] <- quantile(select(filter(NoOutliersSpeed,
                                                      DirChange2 == "Same"
                                                     ),
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

TravTimeSec_Qtiles_df[ , 4] <- quantile(select(filter(NoOutliersSpeed,
                                                      DirChange2 == "Change"
                                                     ),
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

View(TravTimeSec_Qtiles_df)

Limit the dataset now based on TravelTime_Sec.


UpperLimitTravTime <- filter(NoOutliersSpeed,
                             TravelTime_Sec <= 491 # min at the 100th percentile
                             )

nrow(NoOutliersSpeed) - nrow(UpperLimitTravTime)

str(UpperLimitTravTime)

summary(UpperLimitTravTime)

Investigation of Dwell_Time2 (how long the bus is at a stop).

Differences between Dwell_Time (by WMATA) and Dwell_Time2 (by me) appear to be due to switches in RouteAlt. WMATA calculates Dwell_Time by an unknown process. The WMATA calculation is equal to my calculation, except for the records immedaitely before and after a RouteAlt switch (DirChange2).


View(filter(AllDays_NewOrder,
            Dwell_Time != Dwell_Time2
           )
    )


# Examples where the Dwell_Time and Dwell_Time2 are different
View(filter(AllDays_NewOrder,
            ( (RowNum_OG >= 65 & RowNum_OG <= 85) | # 75
                (RowNum_OG >= 162 & RowNum_OG <= 192) | # 172
                (RowNum_OG >= 431952 & RowNum_OG <= 431972) | # 431962
                (RowNum_OG >= 434595 & RowNum_OG <= 434615) # 434605  --  this record is NOT a route switch, but does has a Sequence switch (Me: should there really be a route switch here?)
            )
           )
    )

Investigation of Dwell_Time2 (how long the bus is at a stop).

First, create some “rank” stats. View(DT2_Pctiles): 95% of Dwell_Time2s are <= 23 seconds…but some weird (e.g., nearly 2 hour Dwell_Time2s exist).


DwellTime2_Ntile <- as.data.frame(AllDays_NewOrder$Dwell_Time2) %>% 
  mutate(Pctile = ntile(AllDays_NewOrder$Dwell_Time2, 100),
         MinR = min_rank(AllDays_NewOrder$Dwell_Time2),
         PctR = percent_rank(AllDays_NewOrder$Dwell_Time2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DwellTime2_Ntile)[1] <- "Dwell_Time2"
str(DwellTime2_Ntile)

DwellTime2_Ntile_Rows <- nrow(DwellTime2_Ntile)

View(tail(DwellTime2_Ntile, 500))


DwellTime2_Pctiles <- group_by(DwellTime2_Ntile,
                               PctR_Round
                              ) %>% 
  summarise(
    MinDwellAtPctile = min(Dwell_Time2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DwellTime2_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DwellTime2_Pctiles)

Investigation of Dwell_Time2 (how long the bus is at a stop).

Histogram of Dwell_Time2.


DwellTime2_HistDen <- ggplot(AllDays_NewOrder, aes(x = Dwell_Time2, y = ..density..)) +
  geom_histogram(binwidth = 1, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(1, 25), ylim = c(0, 0.05)
                 ) +
  xlab("Time a Bus Stays at a Stop (sec)") + 
  ylab("Density") + 
  #  theme(legend.position="none") + 
  ggtitle(expression(atop("Variation in How Long a Bus Stays at a Stop"
                          # ,atop(italic("xxxxx"),"")
                         )
                    )
         )

DwellTime2_HistDen

Investigation of Dwell_Time2 (how long the bus is at a stop).

Looking at some weirdly long Dwell_Time2 values.


View(arrange(AllDays_NewOrder,
             desc(Dwell_Time2)
            )
    )


# examples of extremely large Dwell_Time2s
View(filter(AllDays_NewOrder,
            (RowNum_OG >= 292669 & RowNum_OG <= 292689) | # 292679
                (RowNum_OG >= 531057 & RowNum_OG <= 531077) | # 531067
                (RowNum_OG >= 1388627 & RowNum_OG <= 1388647) | # 1388637
                (RowNum_OG >= 1645711 & RowNum_OG <= 1645731) # 1645721
           )
    )


View(filter(AllDays_NewOrder,
            Dwell_Time2 == 0
           )
    )

Investigation of Delta_Time (how early or late the bus is).

View(DT2_Pctiles): 94% of Delta_Time values are between -236 seconds and 1,259 seconds. Roughly 66% of records are within 5 min late and 5 min early…but some weird (e.g., almost 50 minute late or 40 minute early) Delta_Times exist.

Note that Delta_Time is the difference from the scheduled bus arrival. So if two buses are scheduled to arrive at a destination at 10:00pm and 10:20pm, and if the 10:20pm bus has a Delta_Time of 5 minutes, there are 25 minutes between bus arrivals at the stop.

Also note that based on a comment at https://planitmetro.com/2016/11/16/data-download-metrobus-vehicle-location-data/, the Delta_Time values don’t appear to coincide with published bus schedules (e.g., the X2 departing every 8 minutes during peak hours).


DeltTime_Ntile <- as.data.frame(AllDays_NewOrder$Delta_Time) %>% 
  mutate(Pctile = ntile(AllDays_NewOrder$Delta_Time, 100),
         MinR = min_rank(AllDays_NewOrder$Delta_Time),
         PctR = percent_rank(AllDays_NewOrder$Delta_Time),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DeltTime_Ntile)[1] <- "Delta_Time"
str(DeltTime_Ntile)

DeltTime_Ntile_Rows <- nrow(DeltTime_Ntile)

View(tail(DeltTime_Ntile, 500))


DeltTime_Pctiles <- group_by(DeltTime_Ntile,
                             PctR_Round
                            ) %>% 
  summarise(
    MinDeltTimeAtPctile = min(Delta_Time),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DeltTime_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DeltTime_Pctiles)
DeltTime_Pctiles

# ~66% of rows are between 5 min late and 5 min early
nrow(filter(AllDays_NewOrder,
            Delta_Time >= -300 &
              Delta_Time <= 300
           )
    ) / nrow(AllDays_NewOrder)


# examples of weird large Delta_Times
View(filter(AllDays_NewOrder,
            Delta_Time < -4202 |
              Delta_Time > 1705
           ) %>% 
       arrange(desc(Delta_Time)
              )
    )

Investigation of Delta_Time (how early or late the bus is).

Delta_Time histogram.


DeltTime_HistDen <- ggplot(AllDays_NewOrder, aes(x = (Delta_Time / 60),
                                                 y = ..density..
                                                )
                          ) +
  geom_histogram(binwidth = (5/60), fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(-5, 5)) +
  xlab("Bus Lateness (min)") + 
  ylab("Density") + 
  #  theme(legend.position="none") + 
  ggtitle(expression(atop("Variation in How Early/Late a Bus Is",
                          atop(italic("(positive values are late arrivals)"),
                               ""
                              )
                         )
                    )
         )

DeltTime_HistDen

Investigation of Delta_Time (how early or late the bus is).

Delta_Time boxplot.


# Count_Values is needed to display the medians on the box plots
Count_Values <- ddply(AllDays_NewOrder,
                      .(Event_Time_HrGroup),
                      summarise,
                      Value_Counts = median(Delta_Time / 60, na.rm = TRUE)
                     )

DeltTime_BoxPlot <- ggplot(AllDays_NewOrder,
                           aes(factor(Event_Time_HrGroup),
                               Delta_Time / 60,
                               fill = factor(Event_Time_HrGroup)
                              )
                          ) + 
  geom_boxplot(outlier.colour="red", notch=TRUE) + 
  # coord_cartesian(ylim = c(-300, 1200)) +
  coord_cartesian(ylim = c(-5, 20)) +
  geom_text(data = Count_Values,
            aes(y = Value_Counts,
                label = format(round(Value_Counts, digits = 1),
                               nsmall = 1
                              )
               ),
            size = 3,
            vjust = -0.5
           ) +
  xlab("Hour Group") + 
  ylab("Bus Lateness (minutes)") + 
  theme(legend.position="none", axis.text.x = element_text(angle=45)) + 
  #theme(legend.position="right", axis.text.x = element_blank()) + 
  ggtitle(expression(atop("How Early/Late is the Bus (by Hour Group)",
                          atop(italic("(positive values are late arrivals)"),
                               ""
                              )
                         )
                    )
         )

DeltTime_BoxPlot

Investigation of Delta_Time (how early or late the bus is).

Exploring “extreme” Delta_Times. First let’s get some “rank” stats.


View(DeltTime_Pctiles)
DeltTime_Pctiles


DeltTimeAbs_Ntile <- as.data.frame(abs(AllDays_NewOrder$Delta_Time)) %>% 
  mutate(Pctile = ntile(abs(AllDays_NewOrder$Delta_Time), 100),
         MinR = min_rank(abs(AllDays_NewOrder$Delta_Time)),
         PctR = percent_rank(abs(AllDays_NewOrder$Delta_Time)),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DeltTimeAbs_Ntile)[1] <- "Delta_Time_Abs"
str(DeltTimeAbs_Ntile)

DeltTimeAbs_Ntile_Rows <- nrow(DeltTimeAbs_Ntile)

View(tail(DeltTimeAbs_Ntile, 500))


DeltTimeAbs_Pctiles <- group_by(DeltTimeAbs_Ntile,
                                PctR_Round
                               ) %>% 
  summarise(
    MinDeltTimeAtPctile = min(Delta_Time_Abs),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DeltTime_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DeltTimeAbs_Pctiles)
DeltTimeAbs_Pctiles

Investigation of Delta_Time (how early or late the bus is).

Exploring “extreme” Delta_Times. Then let’s calculate the percentage of buses that are 10 minutes (or more) late/early.


HrGroup_DeltaTime_All <- group_by(AllDays_NewOrder,
                                  Event_Time_HrGroup
                                 ) %>% 
  summarise(EventAll_Cnt = n()
           )

str(HrGroup_DeltaTime_All)
View(HrGroup_DeltaTime_All)


HrGroup_DeltaTime_Above10Min <- filter(AllDays_NewOrder,
                                       abs(Delta_Time) >= 600
                                      ) %>% 
  group_by(Event_Time_HrGroup) %>% 
  summarise(EventAbove10_Cnt = n()
           )

str(HrGroup_DeltaTime_Above10Min)
View(HrGroup_DeltaTime_Above10Min)


HrGroup_DeltaTimeCompare <- inner_join(HrGroup_DeltaTime_Above10Min,
                                       HrGroup_DeltaTime_All,
                                       by = c("Event_Time_HrGroup" = "Event_Time_HrGroup")
                                      ) %>% 
  mutate(PctEventsAbove10 = EventAbove10_Cnt / EventAll_Cnt)

View(HrGroup_DeltaTimeCompare)

Investigation of Delta_Time (how early or late the bus is).

Quickly plot these “extreme” Delta_Times.


DeltTime_Above10_Cols <- ggplot(HrGroup_DeltaTimeCompare,
                                aes(factor(Event_Time_HrGroup),
                                    PctEventsAbove10
                                   )
                               ) +
  geom_col(fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_text(aes(label = format(round(PctEventsAbove10, digits = 2),
                               nsmall = 2
                              )
               ),
            size = 3,
            nudge_y = (HrGroup_DeltaTimeCompare$PctEventsAbove10 * -0.1)
           ) +
  # coord_cartesian(xlim = c(-5, 5)) +
  xlab("Hour Group") + 
  ylab("Percent of All Bus Arrivals") +
  theme(legend.position="none", axis.text.x = element_text(angle=45)) +
  ggtitle(expression(atop("When is a Bus 10+ Minutes Late/Early"
                          # ,atop(italic("positive values are late arrivals"),
                          #      ""
                          #     )
                         )
                    )
         )

DeltTime_Above10_Cols

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Correlation.


DwellTDeltaT_Corr <- as.matrix(cor(x = AllDays_NewOrder$Dwell_Time2,
                                   y = AllDays_NewOrder$Delta_Time,
                                   use = "pairwise"
                                  )
                               )

DwellTDeltaT_Corr

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Next, let’s get a sample of data for plotting. Let’s do this for the full dataset (AllDays_NewOrder).


AllDays_NewOrder_10PctSamp <- sample_frac(AllDays_NewOrder, 0.1) %>% 
  select(Delta_Time,
         Dwell_Time2
        ) %>% 
  mutate(DataSet = "AllData")

str(AllDays_NewOrder_10PctSamp)

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Let’s also get a sample of data for plotting, but with a datset that removes outliers.


View(DeltTime_Pctiles)
View(DwellTime2_Pctiles)

AllDays_NewOrder_NoExtremes_10PctSamp <- filter(AllDays_NewOrder,
                                                between(Delta_Time, -402, 1705) & # removes about 2% of Delta_Time values
                                                  between(Dwell_Time2, 1, 63)  # removes about 2% of Dwell_Time2 values
                                               ) %>% 
  sample_frac(0.1) %>% 
  select(Delta_Time,
         Dwell_Time2
        ) %>% 
  mutate(DataSet = "OutliersRemoved")

str(AllDays_NewOrder_NoExtremes_10PctSamp)

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from the dataset that does not remove outliers.


DwellTDeltaT_Scatter <- ggplot(AllDays_NewOrder_10PctSamp,
                               aes(Dwell_Time2, Delta_Time)
                              ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "red") +
  # xlab("Time at Stop (sec)") + 
  # ylab("Lateness (sec)") +
  annotate(label = lm_eqn(df = AllDays_NewOrder_10PctSamp,
                          y = AllDays_NewOrder_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_10PctSamp$Dwell_Time2
                         ),
           x = 2200,
           y = 600,
           geom = "text",
           size = 3,
           colour = "red",
           parse = TRUE
          ) +
  labs(title = "Lateness vs Time at Stop",
       subtitle = "(no outliers removed)",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
  #                         ,atop(italic("(no outliers removed)"),
  #                               ""
  #                              )
  #                        )
  #                   )
  #        )
# +
#   geom_jitter()

DwellTDeltaT_Scatter

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from the dataset that does remove outliers.


DwellTDeltaT_Scatter_NoExtremes <- ggplot(AllDays_NewOrder_NoExtremes_10PctSamp,
                                          aes(Dwell_Time2, Delta_Time)
                                         ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "blue") +
  # xlab("Time at Stop (sec)") + 
  # ylab("Lateness (sec)") +
  annotate(label = lm_eqn(df = AllDays_NewOrder_NoExtremes_10PctSamp,
                          y = AllDays_NewOrder_NoExtremes_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_NoExtremes_10PctSamp$Dwell_Time2
                         ),
           x = 50,
           y = -475,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  labs(title = "Lateness vs Time at Stop",
       subtitle = "(2% of outliers removed)",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
  #                         ,atop(italic("(2% of outliers removed)"),
  #                               ""
  #                              )
  #                        )
  #                   )
  #        )
# +
#   geom_jitter()

DwellTDeltaT_Scatter_NoExtremes

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from both datasets together.


CombinedData <- rbind(AllDays_NewOrder_10PctSamp,
                      AllDays_NewOrder_NoExtremes_10PctSamp
                     )

CombinedData$DataSet <- factor(CombinedData$DataSet)

str(CombinedData)


DwellTDeltaT_Scatter_Combined <- ggplot(CombinedData,
                                        aes(x = Dwell_Time2,
                                            y = Delta_Time,
                                            colour = DataSet
                                           )
                                       ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  coord_cartesian(xlim = c(0, 500), ylim = c(-1000, 2000)
                 ) +
  geom_smooth(data = filter(CombinedData,
                            DataSet == "AllData"
                           ),
              method = "lm",
              colour = "red"
             ) +
  geom_smooth(data = filter(CombinedData,
                            DataSet == "OutliersRemoved"
                           ),
              method = "lm",
              colour = "blue"
             ) +
  # facet_wrap( ~ DataSet, ncol = 2) +
  annotate(label = lm_eqn(df = AllDays_NewOrder_10PctSamp,
                          y = AllDays_NewOrder_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_10PctSamp$Dwell_Time2
                         ),
           x = 300,
           y = -600,
           geom = "text",
           size = 3,
           colour = "red",
           parse = TRUE
          ) +
  annotate(label = lm_eqn(df = AllDays_NewOrder_NoExtremes_10PctSamp,
                          y = AllDays_NewOrder_NoExtremes_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_NoExtremes_10PctSamp$Dwell_Time2
                         ),
           x = 300,
           y = -800,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  theme(legend.position = "bottom") +
  labs(title = "Lateness vs Time at Stop",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
                          # ,atop(italic("2% of outliers removed"),
                          #       ""
                          #      )
         #                 )
         #            )
         # )
# +
#   geom_jitter()

DwellTDeltaT_Scatter_Combined

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayBmb3IgV01BVEEgTWV0cm9idXMgRGF0YSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2sgZm9yIGFuYWx5c2lzIHVzaW5nIGRhdGEgb24gdGhlIERDIEJ1cyBTeXN0ZW0gKFdNQVRBIE1ldHJvYnVzKS4gIFRoZSBkYXRhIHdlcmUgb2J0YWluZWQgaGVyZToKCmh0dHBzOi8vcGxhbml0bWV0cm8uY29tLzIwMTYvMTEvMTYvZGF0YS1kb3dubG9hZC1tZXRyb2J1cy12ZWhpY2xlLWxvY2F0aW9uLWRhdGEvCgpDb250cm9sICsgQWx0ICsgU2hpZnQgKyBtID0gcmVuYW1lIGluIHNjb3BlCgpMb2FkIHRoZSBwYWNrYWdlcyB0byBiZSB1c2VkLgpgYGB7ciBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KCmxpYnJhcnkoImpzb25saXRlIikKbGlicmFyeSgidGlkeXIiKQpsaWJyYXJ5KCJwbHlyIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJtYWdyaXR0ciIpCmxpYnJhcnkoInN0cmluZ3IiKQpsaWJyYXJ5KCJkYXRhLnRhYmxlIikKbGlicmFyeSgibHVicmlkYXRlIikKbGlicmFyeSgiZ2Vvc3BoZXJlIikKbGlicmFyeSgiZ2dwbG90MiIpCmxpYnJhcnkoImdndmlzIikKbGlicmFyeSgicmJva2VoIikKCmBgYAoKCkdldCB0aGUgQnVzIGRhdGEuCgpGaXJzdCBsZXQncyBjaGVjayB0aGUgd29ya2luZyBkaXJlY3RvcnkuCmBgYHtyfQoKZ2V0d2QoKQoKYGBgCgoKVGhlbiwgYWN0dWFsbHkgZ2V0IHRoZSBkYXRhLgpgYGB7ciBlY2hvID0gRkFMU0V9CgpzZXR3ZCgiL1VzZXJzL21kdHVyc2UvRGVza3RvcC9BbmFseXRpY3MvRENNZXRyb0J1cy9CdXMgQVZMIE9jdCAyMDE2IikKCmZvciAoaSBpbiAzOjcpewogIGFzc2lnbihwYXN0ZTAoIk9jdDAiLCBpLCAiUmF3IiksCiAgICAgICAgIHJlYWQuZGVsaW0ocGFzdGUwKCIyMDE2MTAwIiwgaSwgIk1ldHJvYnVzQVZMLnR4dCIpLAogICAgICAgICAgICAgICAgICAgIHNlcCA9ICJcdCIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICBuYS5zdHJpbmdzID0gTlVMTAogICAgICAgICAgICAgICAgICAgKQogICAgICAgICkKICAKICBtZXNzYWdlKCJPY3QwIiwgaSwgIlJhdyIpCiAKICBzdHIoZ2V0KHBhc3RlMCgiT2N0MCIsIGksICJSYXciKQogICAgICAgICApCiAgICAgKQogIH0KCmBgYAoKClB1dCB0aGUgZGFpbHkgZGF0YSB0b2dldGhlci4KYGBge3J9CgpBbGxEYXlzIDwtIGJpbmRfcm93cyhsaXN0KE9jdDAzUmF3LCBPY3QwNFJhdywgT2N0MDVSYXcsIE9jdDA2UmF3LCBPY3QwN1JhdyksCiAgICAgICAgICAgICAgICAgICAgIC5pZCA9IGMoImdyb3VwIikKICAgICAgICAgICAgICAgICAgICApCiMgZGltKEFsbERheXMpCnN0cihBbGxEYXlzKQoKYGBgCgoKRGVsZXRpbmcgb2xkIGRhdGEgZnJhbWVzLgpgYGB7cn0KCmZvciAoaSBpbiAzOjcpewogIHJtKGxpc3QgPSBscyhwYXR0ZXJuID0gcGFzdGUwKCJPY3QwIiwgaSwgIlJhdyIpCiAgICAgICAgICAgICAgKQogICAgKQogIAogIG1lc3NhZ2UoIkRlbGV0aW5nIE9jdDAiLCBpLCAiUmF3IikKICB9CgpgYGAKCgpVcGRhdGluZyB2YXJpYWJsZSB0eXBlcy4KClRoZW4sIHNvcnRpbmcgdGhlIGRhdGEgYW5kIGFkZGluZyBhIFJvd051bWJlciAodG8gYmUgdXNlZCBmb3IgaWRlbnRpZnlpbmcgcm93cyBsYXRlciBpbiB0aGUgYW5hbHlzZXMuKQpgYGB7cn0KCnJtKGkpCgoKQWxsRGF5cyRncm91cCA8LSBmYWN0b3IoQWxsRGF5cyRncm91cCkKQWxsRGF5cyRSb3V0ZV9EaXJlY3Rpb24gPC0gZmFjdG9yKEFsbERheXMkUm91dGVfRGlyZWN0aW9uKQpBbGxEYXlzJEV2ZW50X1RpbWUgPC0gYXMuUE9TSVhjdChBbGxEYXlzJEV2ZW50X1RpbWUsIGZvcm1hdCA9ICIlbS0lZC0leSAlSTolTTolUyAlcCIpCkFsbERheXMkRGVwYXJ0dXJlX1RpbWUgPC0gYXMuUE9TSVhjdChBbGxEYXlzJERlcGFydHVyZV9UaW1lLCBmb3JtYXQgPSAiJW0tJWQtJXkgJUk6JU06JVMgJXAiKQoKc3RyKEFsbERheXMpCgoKQWxsRGF5c19Tb3J0ZWQgPC0gYXJyYW5nZShBbGxEYXlzLAogICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c19JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lCiAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoUm93TnVtX09HID0gcm93X251bWJlcigpICMgdGhpcyBpcyB1c2VmdWwgaW4gaWRlbnRpZnkgdGhlIHJvdyBsYXRlciBvbgogICAgICAgICkKCnJtKEFsbERheXMpCnN0cihBbGxEYXlzX1NvcnRlZCkKCiMgVmlldyhoZWFkKEFsbERheXNfU29ydGVkLCAxMDApKQoKYGBgCgoKSW5zcGVjdGluZyB0aGUgdmFsdWVzIG9mIFN0b3BfSUQsIGFuZCBmaW5kaW5nIHRoYXQgaXQgY2FuIHRha2UgdGhlIHZhbHVlcyAiIiAoYmxhbmspIGFuZCAiTlVMTCIuCmBgYHtyfQoKVmlldyhncm91cF9ieShBbGxEYXlzX1NvcnRlZCwKICAgICAgICAgICAgICBTdG9wX0lECiAgICAgICAgICAgICApICU+JSAKICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgQ250ID0gbigpCiAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShTdG9wX0lEKQogICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19Tb3J0ZWQsCiAgICAgICAgICAgIGlzLm5hKFN0b3BfSUQpIHwKICAgICAgICAgICAgICBTdG9wX0lEID09ICIiIHwKICAgICAgICAgICAgICBTdG9wX0lEID09ICJOVUxMIgogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShTdG9wX0Rlc2MpCiAgICApCgpgYGAKCgpDcmVhdGluZyBhIHRhYmxlIG9mIGRpc3RpbmN0IFN0b3BfRGVzYyB2YWx1ZXMgd2hlbiBTdG9wX0lEIGlzICIiIChibGFuaykgb3IgIk5VTEwiLgpgYGB7cn0KClN0b3BJRF9OZXcgPC0gZmlsdGVyKEFsbERheXNfU29ydGVkLAogICAgICAgICAgICAgICAgICAgICBpcy5uYShTdG9wX0lEKSB8CiAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9JRCA9PSAiIiB8CiAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9JRCA9PSAiTlVMTCIKICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzZWxlY3QoU3RvcF9JRCwgU3RvcF9EZXNjKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgYXJyYW5nZShTdG9wX0lELCBTdG9wX0Rlc2MpICU+JSAKICBtdXRhdGUoU3RvcElEX05ldyA9IDE6bnJvdyguKQogICAgICAgICkKClZpZXcoU3RvcElEX05ldykKCmBgYAoKCkNyZWF0aW5nIGEgZnVsbCB1cGRhdGVkIHRhYmxlIGJ5IGZpbGxpbmcgaW4gU3RvcElEX05ldyBmb3Igd2hlbiBTdG9wX0lEIGlzICIiIChibGFuaykgb3IgTlVMTC4KYGBge3J9CgpBbGxEYXlzX1N0b3BJRE5ldyA8LSBsZWZ0X2pvaW4oQWxsRGF5c19Tb3J0ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoU3RvcElEX05ldywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wX0Rlc2MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcElEX05ldwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiU3RvcF9EZXNjIiA9ICJTdG9wX0Rlc2MiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoU3RvcElEX0NsZWFuID0gaWZlbHNlKGlzLm5hKFN0b3BJRF9OZXcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BJRF9OZXcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgU3RvcElEX0luZGljYXRvciA9IGZhY3RvcihpZmVsc2UoaXMubmEoU3RvcElEX05ldyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJRF9PSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJRF9CYWQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkKCnJtKFN0b3BJRF9OZXcpCnJtKEFsbERheXNfU29ydGVkKQpzdHIoQWxsRGF5c19TdG9wSUROZXcpCgojIFZpZXcodGFpbChBbGxEYXlzX1N0b3BJRE5ldywgNTAwKSkKIyBWaWV3KGZpbHRlcihBbGxEYXlzX1N0b3BJRE5ldywKIyAgICAgICAgICAgICBTdG9wX0Rlc2MgPT0gIk1FVFJPV0FZIEFOTk5PVUNFTU5UIENPUlIiCiMgICAgICAgICAgICApCiMgICAgICkKCmBgYAoKCgpMYXQgTG9uZyBzdGF0cyBmb3IgcHVsbGluZyBpbiBaaXAgY29kZXMgbGF0ZXIuCmBgYHtyfQoKTExfU3RhdHMgPC0gZ3JvdXBfYnkoQWxsRGF5c19TdG9wSUROZXcsCiAgICAgICAgICAgICAgICAgICAgIFN0b3BJRF9DbGVhbgogICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZShMYXRfTWVhbiA9IG1lYW4oTGF0aXR1ZGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIExhdF9NZWQgPSBtZWRpYW4oTGF0aXR1ZGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIExuZ19NZWFuID0gbWVhbihMb25naXR1ZGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIExuZ19NZWQgPSBtZWRpYW4oTG9uZ2l0dWRlLCBuYS5ybSA9IFRSVUUpCiAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKExhdF9NZWFMZXNzTWVkID0gTGF0X01lYW4gLSBMYXRfTWVkLAogICAgICAgICBMbmdfTWVhTGVzc01lZCA9IExuZ19NZWFuIC0gTG5nX01lZCwKICAgICAgICAgUm93TnVtID0gcm93X251bWJlcigpCiAgICAgICAgKQoKc3RyKExMX1N0YXRzKQpzdW1tYXJ5KExMX1N0YXRzKQoKVmlldyhoZWFkKGFycmFuZ2UoTExfU3RhdHMsCiAgICAgICAgICAgICAgICAgIExhdF9NZWFMZXNzTWVkCiAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgIDUwMAogICAgICAgICApCiAgICApCgpWaWV3KGhlYWQoYXJyYW5nZShMTF9TdGF0cywKICAgICAgICAgICAgICAgICAgZGVzYyhMYXRfTWVhTGVzc01lZCkKICAgICAgICAgICAgICAgICApLAogICAgICAgICAgNTAwCiAgICAgICAgICkKICAgICkKClZpZXcoaGVhZChhcnJhbmdlKExMX1N0YXRzLAogICAgICAgICAgICAgICAgICBMbmdfTWVhTGVzc01lZAogICAgICAgICAgICAgICAgICksCiAgICAgICAgICA1MDAKICAgICAgICAgKQogICAgKQoKVmlldyhoZWFkKGFycmFuZ2UoTExfU3RhdHMsCiAgICAgICAgICAgICAgICAgIGRlc2MoTG5nX01lYUxlc3NNZWQpCiAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgIDUwMAogICAgICAgICApCiAgICApCgpgYGAKCgpQdWxsaW5nIGluIFppcCBDb2RlIGRhdGEgZnJvbSBhcGkuZ2VvbmFtZXMub3JnLgpgYGB7cn0KCiMgVVJMIEVYQU1QTEU6CiMgaHR0cDovL2FwaS5nZW9uYW1lcy5vcmcvZmluZE5lYXJieVBvc3RhbENvZGVzSlNPTj9sYXQ9MzguODk1NjAmbG5nPS03Ni45NDg3MyZyYWRpdXM9MCZ1c2VybmFtZT1zdXBlcm1kYXQKCnVybF8xIDwtICJodHRwOi8vYXBpLmdlb25hbWVzLm9yZy9maW5kTmVhcmJ5UG9zdGFsQ29kZXNKU09OP2xhdD0iCnVybF8yIDwtICImbG5nPSIKdXJsXzMgPC0gIiZyYWRpdXM9MCZ1c2VybmFtZT0iCnVzZXJuYW1lIDwtICJzdXBlcm1kYXQiCgoKIyBuZWVkIHRvIGdyb3VwIGluIGJ1bmNoZXMgYXMgaHR0cDovL2FwaS5nZW9uYW1lcy5vcmcgbGltaXRzIHB1bGxzIHRvIDIwMDAgcGVyIGhvdXIKCgojIyMjIyBTdG9yZSBldmVyeXRoaW5nIGluIG11bHRpcGxlIGxpc3RzCnBhZ2VzMSA8LSBsaXN0KCkKCgpzeXN0ZW0udGltZSgKIyAgIGZvcihqIGluIDA6NSl7CiMgICBmb3IoayBpbiAoKG1heF9yb3dfcGVyX2hyKmopICsgMSk6KG1heF9yb3dfcGVyX2hyKihqKzEpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgKXsKIyAgICAgCiMgICB9CiMgfQpmb3IoaSBpbiAxOjEwMDApewogIGxhdCA8LSBmaWx0ZXIoTExfU3RhdHMsCiAgICAgICAgICAgICAgICBSb3dOdW0gPT0gaQogICAgICAgICAgICAgICApICU+JQogICAgc2VsZWN0KExhdF9NZWQpCiAgCiAgbG5nIDwtIGZpbHRlcihMTF9TdGF0cywKICAgICAgICAgICAgICAgIFJvd051bSA9PSBpCiAgICAgICAgICAgICAgICkgJT4lCiAgICBzZWxlY3QoTG5nX01lZCkKICAKICBBUElEYXRhMSA8LSBmcm9tSlNPTihwYXN0ZTAodXJsXzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsXzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxuZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsXzMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJuYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICBmbGF0dGVuID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgKQogIAogIG1lc3NhZ2UoIlJldHJpZXZpbmcgWmlwIENvZGUgIiwgaSkKICAKICBwYWdlczFbW2ldXSA8LSBBUElEYXRhMSRwb3N0YWxDb2RlcwogIAogICMgU3lzLnNsZWVwKDM5MDApCn0KKQoKIyBjbGFzcyhBUElEYXRhMSkKIyBjbGFzcyhBUElEYXRhMiRwb3N0YWxDb2RlcykKIyBzdHIoQVBJRGF0YTEpCiMgaGVhZChBUElEYXRhMSkKIyBjbGFzcyhwYWdlczEpCiMgc3RyKHBhZ2VzMSkKIyBucm93KHBhZ2UxKQojIG5jb2wocGFnZTEpCiMgcGFnZXMxW1sxMTk5XV0KIyBwYWdlczFbWzIwNTFdXQoKCiMjIyMjIENvbWJpbmUgdGhlIGxpc3RzIGludG8gb25lIHBhZ2UKWmlwczEgPC0gcmJpbmQucGFnZXMocGFnZXMxW3NhcHBseShwYWdlczEsIGxlbmd0aCkgPiAwXSkKCgojIyMjIyBDb21iaW5lIGFsbCBwYWdlcwpaaXBzX0FsbCA8LSBiaW5kX3Jvd3MoWmlwczAsCiAgICAgICAgICAgICAgICAgICAgICBaaXBzMSwKICAgICAgICAgICAgICAgICAgICAgIFppcHMyLAogICAgICAgICAgICAgICAgICAgICAgWmlwczMsCiAgICAgICAgICAgICAgICAgICAgICBaaXBzNCwKICAgICAgICAgICAgICAgICAgICAgIFppcHM1LAogICAgICAgICAgICAgICAgICAgICAgWmlwczYsCiAgICAgICAgICAgICAgICAgICAgICBaaXBzNywKICAgICAgICAgICAgICAgICAgICAgIFppcHM4LAogICAgICAgICAgICAgICAgICAgICAgWmlwczksCiAgICAgICAgICAgICAgICAgICAgICBaaXBzMTAsCiAgICAgICAgICAgICAgICAgICAgICAjIFppcHMxX2EsCiAgICAgICAgICAgICAgICAgICAgICAuaWQgPSAiaWQiCiAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShVbmlxdWVMYXRMbmcgPSBwYXN0ZShsYXQsIGxuZywgc2VwID0gIl9fIikKICAgICAgICApCgojIHN0cihaaXBzX0FsbCkKIyBWaWV3KGhlYWQoWmlwc19BbGwpKQoKCiMgc3RyKExMX1N0YXRzKQpMTF9TdGF0c19VbnFMYXRMbmcgPC0gbXV0YXRlKExMX1N0YXRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVuaXF1ZUxhdExuZyA9IHBhc3RlKExhdF9NZWQsIExuZ19NZWQsIHNlcCA9ICJfXyIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgojIHN0cihMTF9TdGF0c19VbnFMYXRMbmcpCiMgVmlldyhoZWFkKExMX1N0YXRzX1VucUxhdExuZykpCgoKTExfU3RhdHNaaXBzIDwtIGxlZnRfam9pbihMTF9TdGF0c19VbnFMYXRMbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgWmlwc19BbGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCJVbmlxdWVMYXRMbmciID0gIlVuaXF1ZUxhdExuZyIpCiAgICAgICAgICAgICAgICAgICAgICAgICApCgpzdHIoTExfU3RhdHNaaXBzKQojIFZpZXcoaGVhZChMTF9TdGF0c1ppcHMpKQoKIyBOb3Qgc3VyZSB3aGV5IHRoZXNlIGNvdWxkbid0IGJlIGZvdW5kICh3aHkgdGhleSdyZSBOQSkKVmlldyhmaWx0ZXIoTExfU3RhdHNaaXBzLAogICAgICAgICAgICBpcy5uYShwb3N0YWxDb2RlKQogICAgICAgICAgICkKICAgICkKCmBgYAoKCkpvaW4gdG8gY3JlYXRlIG9uZSBkYXRhc2V0IHRoYXQgYWxzbyBpbmNsdWRlcyBaaXAgdmFyaWFibGVzLgpgYGB7cn0KCnJtKHVybF8xLCB1cmxfMiwgdXJsXzMsIHVzZXJuYW1lLCBwYWdlczAsIHBhZ2VzMSwgcGFnZXMyLCBwYWdlczMsIHBhZ2VzNCwgcGFnZXM1LCBwYWdlczYsIHBhZ2VzNywgcGFnZXM4LCBwYWdlczksIHBhZ2VzMTAsIGksIGxhdCwgbG5nLCBBUElEYXRhMCwgQVBJRGF0YTEsIEFQSURhdGEyLCBBUElEYXRhMywgQVBJRGF0YTQsIEFQSURhdGE1LCBBUElEYXRhNiwgQVBJRGF0YTcsIEFQSURhdGE4LCBBUElEYXRhOSwgQVBJRGF0YTEwLCBMTF9TdGF0cywgTExfU3RhdHNfVW5xTGF0TG5nKQoKCkFsbERheXNfWmlwcyA8LSBsZWZ0X2pvaW4oQWxsRGF5c19TdG9wSUROZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgTExfU3RhdHNaaXBzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiU3RvcElEX0NsZWFuIiA9ICJTdG9wSURfQ2xlYW4iKQogICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgcmVuYW1lKFN0b3BfU3RhdGUgPSBhZG1pbkNvZGUxLAogICAgICAgICBTdG9wX0NvdW50eSA9IGFkbWluTmFtZTIsCiAgICAgICAgIFN0b3BfQ2l0eSA9IHBsYWNlTmFtZSwKICAgICAgICAgU3RvcF9aaXAgPSBwb3N0YWxDb2RlCiAgICAgICAgICkKCnJtKEFsbERheXNfU3RvcElETmV3LCBMTF9TdGF0c1ppcHMpCnN0cihBbGxEYXlzX1ppcHMpCgpgYGAKCgpVcGRhdGluZyB2YXJpYWJsZSB0eXBlcy4KYGBge3J9CgpBbGxEYXlzX1ppcHMkU3RvcF9TdGF0ZSA8LSBmYWN0b3IoQWxsRGF5c19aaXBzJFN0b3BfU3RhdGUpCkFsbERheXNfWmlwcyRTdG9wX0NvdW50eSA8LSBmYWN0b3IoQWxsRGF5c19aaXBzJFN0b3BfQ291bnR5KQpBbGxEYXlzX1ppcHMkU3RvcF9aaXAgPC0gZmFjdG9yKEFsbERheXNfWmlwcyRTdG9wX1ppcCkKQWxsRGF5c19aaXBzJFN0b3BfQ2l0eSA8LSBmYWN0b3IoQWxsRGF5c19aaXBzJFN0b3BfQ2l0eSkKCkFsbERheXNfWmlwcyRkaXN0YW5jZSA8LSBhcy5udW1lcmljKEFsbERheXNfWmlwcyRkaXN0YW5jZSkKQWxsRGF5c19aaXBzJGNvdW50cnlDb2RlIDwtIGZhY3RvcihBbGxEYXlzX1ppcHMkY291bnRyeUNvZGUpCkFsbERheXNfWmlwcyRhZG1pbk5hbWUxIDwtIGZhY3RvcihBbGxEYXlzX1ppcHMkYWRtaW5OYW1lMSkKCnN0cihBbGxEYXlzX1ppcHMpCgpgYGAKCgpGZWF0dXJlIGVuZ2luZWVyaW5nLgoKSW5zcGVjdGluZyBpbmNpZGVuY2VzIG9mIGNvbnNlY3V0aXZlIFN0b3BfSURzLiBUaGlzIGlzIGRvbmUgYmVjYXVzZSBpbnZlc3RpZ2F0aW9uIHNob3dlZCB0aGF0IG1hbnkgY29uc2V1dGl2ZSBldmVudHMgb2NjdXJyIGF0IHRoZSBzYW1lIFN0b3BfSUQsIGJ1dCB3aXRoIHZhcmlvdXMgRHdlbGxfVGltZXMsIE9kb21ldGVyX0Rpc3RhbmNlcywgZXRjLiAgQWxsIG9mIHdoaWNoIGFmZmVjdCBjYWxjdWxhdGlvbnMgYW5kIGFuYWx5c2VzLgoKQ3JlYXRlIGRhdGEgb24gdGhlIHJ1bnMgKGNvbnNlY3V0aXZlIFN0b3BfSURzKS4KYGBge3J9CgpTdG9wSURfUnVucyA8LSBybGUoQWxsRGF5c19aaXBzJFN0b3BJRF9DbGVhbikKClN0b3BJRF9SdW5zJGVuZHMgPC0gY3Vtc3VtKFN0b3BJRF9SdW5zJGxlbmd0aHMpCgpTdG9wSURfUnVucyRzdGFydHMgPC0gaWZlbHNlKGlzLm5hKGxhZyhTdG9wSURfUnVucyRlbmRzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhZyhTdG9wSURfUnVucyRlbmRzKSArIDEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCnN0cihTdG9wSURfUnVucykKIyBjbGFzcyhTdG9wSURfUnVucykKIyAKIyBTdG9wSURfUnVuc19kZiA8LSBkYXRhLmZyYW1lKHVuY2xhc3MoU3RvcElEX1J1bnMpKQojIHN0cihTdG9wSURfUnVuc19kZikKIyBjbGFzcyhTdG9wSURfUnVuc19kZikKIyBybShTdG9wSURfUnVuc19kZikKCmBgYAoKClRyeWluZyB0byBsaW5rIGRhdGEgb24gUnVuc0dyb3VwcyB3aXRoIHRoZSBvcmlnaW5hbCBkYXRhIChBbGxEYXlzX1NvcnRlZCkuIFRoZSBnb2FsIGlzIHRvIHNlbGVjdCBvbmx5IG9uZSByZWNvcmQgcGVyIFJ1bnNHcm91cCAtIHRoYXQgYmVpbmcgdGhlIHJlY29yZCB3aXRoIHRoZSBsb25nZXN0IER3ZWxsX1RpbWUuCgpJIGF0dGVtcHRlZCB0aGlzIGNvbXB1dGF0aW9uIHVzaW5nIGJvdGggZGF0YS5mcmFtZXMgKGRwbHlyKSBhbmQgZGF0YS50YWJsZXMgKGRhdGEudGFibGUpLiBIb3dldmVyLCB3aXRoIDIsODA5LDA2MiByb3dzIGluIG9uZSBkYXRhc2V0IGFuZCAzLDExOSw0NDMgcm93cyBpbiB0aGUgb3RoZXIgZGF0YXNldCwgdGhlIGN1cnJlbnQgY29tcHV0YXRpb24gdGltZSBpcyBvdmVyIDUgZGF5cy4uLnNvIEknbSB0cnlpbmcgYSBkaWZmZXJlbnQgc3RyYXRlZ3kgdG8gb25seSBzZWxlY3QgdGhlIGZpcnN0IHJlY29yZCBpbiBhIHJ1bi4KYGBge3J9CgojIENyZWF0ZSBhIFJ1bnNHcm91cCB2YXJpYWJsZSBmb3IgZWFjaCBydW4KIyBTdG9wSURfUnVuc19kZiRSdW5zR3JvdXAgPC0gcGFzdGUwKCJnIiwgc2VxKDE6bnJvdyhTdG9wSURfUnVuc19kZikKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgCiMgc3RyKFN0b3BJRF9SdW5zX2RmKQojIGhlYWQoU3RvcElEX1J1bnNfZGYsIDI1KQojIHRhaWwoU3RvcElEX1J1bnNfZGYsIDI1KQojIAojIFN0b3BJRF9SdW5zX2RmIDwtIFN0b3BJRF9SdW5zX2RmICU+JSAKIyAgIG11dGF0ZShSb3dOdW0gPSByb3dfbnVtYmVyKCkKIyAgICAgICAgICkKIyAKIyBzdHIoU3RvcElEX1J1bnNfZGYpCiMgaGVhZChTdG9wSURfUnVuc19kZiwgMjUpCiMgdGFpbChTdG9wSURfUnVuc19kZiwgMjUpCiMgCiMgCiMgIyBDb252ZXJ0aW5nIHRvIGRhdGEudGFibGVzIGZvciwgaG9wZWZ1bGx5LCBpbXByb3ZlZCBwZXJmb3JtYW5jZSAoc3BlZWQpIGluIGNvbXB1dGF0aW9uCiMgU3RvcElEX1J1bnNfZHQgPC0gZGF0YS50YWJsZShTdG9wSURfUnVuc19kZikKIyBzZXRrZXkoU3RvcElEX1J1bnNfZHQsIFJvd051bSkKIyBzdHIoU3RvcElEX1J1bnNfZHQpCiMgCiMgQWxsRGF5c19Tb3J0ZWRfZHQgPC0gZGF0YS50YWJsZShBbGxEYXlzX1NvcnRlZCkKIyBzZXRrZXkoQWxsRGF5c19Tb3J0ZWRfZHQsIFJvd051bV9PRykKIyBzdHIoQWxsRGF5c19Tb3J0ZWRfZHQpCiMgIyBybShBbGxEYXlzX1NvcnRlZF9kdCkKIyAKIyAKIyAjIEFjdHVhbCBsb29wIHRvIHBlcmZvcm0gdGhlIGNvbXB1dGF0aW9ucyBhbmQgbGluayB0byBvcmlnaW5hbCBkYXRhIChBbGxEYXlzX1NvcnRlZF9kdCkKIyBHcm91cERhdGEgPC0gbGlzdCgpCiMgZm9yKGkgaW4gMTpucm93KFN0b3BJRF9SdW5zX2R0KQojICAgICkgewojICAgYXNzaWduKHBhc3RlMCgiZ3JvdXBfIiwgaSksCiMgICAgICAgICAgICBTdG9wSURfUnVuc19kdFtSb3dOdW0gPT0gaSwgUnVuc0dyb3VwXQojICAgICAgICAgICApCiMgCiMgICAgICMjIyMjICBUaGUgY29kZSBiZWxvdyBpcyB0aGUgc2FtZSBjb2RlIGFzIGFib3ZlLCBidXQgZG9uZSB3aXRoIGRwbHlyICAjIyMjIwojIAojICAgICAjIGFzc2lnbihwYXN0ZTAoImdyb3VwXyIsIGkpLAojICAgIyAgICAgICAgZmlsdGVyKFN0b3BJRF9SdW5zX2RmLAojICAgIyAgICAgICAgICAgICAgIFJvd051bSA9PSBpCiMgICAjICAgICAgICAgICAgICApICU+JSAKIyAgICMgICAgICAgICAgc2VsZWN0KFJ1bnNHcm91cCkKIyAgICMgICAgICAgKQojIAojICAgYXNzaWduKHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9zdGFydCIpLAojICAgICAgICAgIFN0b3BJRF9SdW5zX2R0W1Jvd051bSA9PSBpLCBzdGFydHNdCiMgICAgICAgICApCiMgCiMgICBhc3NpZ24ocGFzdGUwKCJncm91cF8iLCBpLCAiX2VuZCIpLAojICAgICAgICAgIFN0b3BJRF9SdW5zX2R0W1Jvd051bSA9PSBpLCBlbmRzXQojICAgICAgICAgKQojIAojICAgYXNzaWduKHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9yb3dzIiksCiMgICAgICAgICAgQWxsRGF5c19Tb3J0ZWRfZHRbUm93TnVtX09HID49IGFzLm51bWVyaWMoZ2V0KHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9zdGFydCIpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgUm93TnVtX09HIDw9IGFzLm51bWVyaWMoZ2V0KHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9lbmQiKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgUnVuc0dyb3VwIDo9IGFzLmNoYXJhY3RlcihnZXQocGFzdGUwKCJncm91cF8iLCBpKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgICAgICAgICAgICAgICAgICBdCiMgCiMgICAgICMjIyMjICBUaGUgY29kZSBiZWxvdyBpcyB0aGUgc2FtZSBhcyB0aGUgY29kZSBhYm92ZSwgYnV0IGRvbmUgd2l0aCBkcGx5ciAgIyMjIyMKIyAKIyAgICAgICAgICAjIGZpbHRlcihBbGxEYXlzX1NvcnRlZCwKIyAgICAgICAgICAjICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywKIyAgICAgICAgICAjICAgICAgICAgICAgICAgIGFzLm51bWVyaWMoZ2V0KHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9zdGFydCIpCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICApLAojICAgICAgICAgICMgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhnZXQocGFzdGUwKCJncm91cF8iLCBpLCAiX2VuZCIpCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICkgJT4lIAojICAgICAgICAgICMgICBtdXRhdGUoUnVuc0dyb3VwID0gYXMuY2hhcmFjdGVyKGdldChwYXN0ZTAoImdyb3VwXyIsIGkpCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICApCiMgICAgICAgICApCiMgCiMgICBHcm91cERhdGFbW2ldXSA8LSBnZXQocGFzdGUwKCJncm91cF8iLCBpLCAiX3Jvd3MiKSkKIyAKIyAgIG1lc3NhZ2UoIlByb2Nlc3NpbmcgR3JvdXAgIiwgaSwgIiBvZiAyLDgwOSwwNjIiKQojIH0KIyAKIyAKIyBHcm91cERhdGFfZGYgPC0gcmJpbmQuZmlsbChHcm91cERhdGEpCiMgc3RyKEdyb3VwRGF0YV9kZikKIyBoZWFkKEdyb3VwRGF0YV9kZikKIyB0YWlsKEdyb3VwRGF0YV9kZikKIyAjIHJtKEdyb3VwRGF0YV9kZikKIyAKIyAKIyBncm91cF8xCiMgZ3JvdXBfMV9zdGFydAojIGdyb3VwXzFfZW5kCiMgZ3JvdXBfMV9yb3dzCiMgZ3JvdXBfMl9yb3dzCiMgZ3JvdXBfM19yb3dzCiMgZ3JvdXBfNTBfcm93cwojIHN0cihncm91cF81MF9yb3dzKQojIGdyb3VwXzI4MDkwNjJfcm93cwojIEdyb3VwRGF0YVtbMV1dCiMgR3JvdXBEYXRhW1s1MF1dCiMgCiMgCiMgIyMjIyMgIFRlc3RpbmcgQXJlYSAoQmVsb3cpICAjIyMjIwojICMjIyMjICBUZXN0aW5nIEFyZWEgKEJlbG93KSAgIyMjIyMKIyAjIyMjIyAgVGVzdGluZyBBcmVhIChCZWxvdykgICMjIyMjCiMgCiMgIyBoZWFkKFN0b3BJRF9SdW5zJHN0YXJ0cywgMjApCiMgIyBoZWFkKEFsbERheXNfTmV3T3JkZXIkU3RvcF9JRCwgMjApCiMgIyAKIyAjIAojICMgZGF0IDwtIGFzLmRhdGEuZnJhbWUoYygxLDEsNyw3LDcsOSw2LDgsMiwyLDIsMSwxLDEsMSwxKSkKIyAjIGNvbG5hbWVzKGRhdClbMV0gPC0gImRhdCIKIyAjIHIgPC0gcmxlKGRhdCRkYXQpCiMgIyBkYXQkcnVuIDwtIHJlcChyJGxlbmd0aHMsIHIkbGVuZ3RocykKIyAjIGRhdCRydW5MYWcgPC0gbGFnKGRhdCRydW4pCiMgIyBkYXQkY29uZCA8LSByZXAociR2YWx1ZXMsIHIkbGVuZ3RocykKIyAjIGRhdAojICMgVmlldyhkYXQpCgpgYGAKCgpXaGVuIGNvbnNlY3V0aXZlIFN0b3BfSUQgb2NjdXJycywgb25seSB0YWtlIHRoZSBmaXJzdCBvY2N1cnJlbmNlLiBUaGlzIGlzIGRvbmUgYmVjYXVzZSB0aGUgY29tcHV0YXRpb24gdGltZSB0byBzZWxlY3Qgb25seSB0aGUgcmVjb3JkIHdpdGggdGhlIGxvbmdlc3QgRHdlbGxfVGltZSBmb3IgZWFjaCBydW4gd2FzIHRvbyBsb25nIChvdmVyIDUgZGF5cykuCgpUaGlzIGlzIHByb2JhYmx5IGxlc3MgdGhhbiBpZGVhbCB3aXRoIHJlZ2FyZHMgdG8gRHdlbGxfVGltZSwgYnV0IHNob3VsZCBub3QgbWFrZSBtdWNoIGRpZmZlcmVuY2UgZm9yIGNhbGN1bGF0aW9ucyBvZiB0cmF2ZWwgdGltZSwgc3BlZWQsIGV0Yy4KYGBge3J9CgpBbGxEYXlzX0ZpcnN0U3RvcElEIDwtIEFsbERheXNfWmlwc1tTdG9wSURfUnVucyRzdGFydHMsIF0KCmRpbShBbGxEYXlzX1ppcHMpCmRpbShBbGxEYXlzX0ZpcnN0U3RvcElEKQoKbnJvdyhBbGxEYXlzX1ppcHMpIC0gbnJvdyhBbGxEYXlzX0ZpcnN0U3RvcElEKQoKcm0oQWxsRGF5c19aaXBzLCBTdG9wSURfUnVucykKc3RyKEFsbERheXNfRmlyc3RTdG9wSUQpCgpgYGAKCgpGZWF0dXJlIGVuZ2luZWVyaW5nLgoKQ3JlYXRpbmcgbmV3IHZhcmlhYmxlcy4KYGBge3J9CgpBbGxEYXlzX0FkZFZhcnMgPC0gbXV0YXRlKEFsbERheXNfRmlyc3RTdG9wSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2VfTWkgPSBPZG9tZXRlcl9EaXN0YW5jZSAvIDUyODAsICM1LDI4MCBmZWV0IGluIDEgbWlsZQogICAgICAgICAgICAgICAgICAgICAgICAgIER3ZWxsX1RpbWUyID0gYXMubnVtZXJpYyhEZXBhcnR1cmVfVGltZSAtIEV2ZW50X1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfWXIgPSBhcy5pbnRlZ2VyKHllYXIoRXZlbnRfVGltZSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfTXRoID0gYXMuaW50ZWdlcihtb250aChFdmVudF9UaW1lKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXRlID0gZGF5KEV2ZW50X1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfRGF5ID0gd2RheShFdmVudF9UaW1lLCBsYWJlbCA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHIgPSBob3VyKEV2ZW50X1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfTWluID0gbWludXRlKEV2ZW50X1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHJHcm91cCA9IGZhY3RvcihpZmVsc2UoRXZlbnRfVGltZV9IciA8IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAwXzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnRfVGltZV9IciA8IDYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAzXzUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnRfVGltZV9IciA8IDksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXA2XzgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnRfVGltZV9IciA8IDEyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwOV8xMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFdmVudF9UaW1lX0hyIDwgMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAxMl8xNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFdmVudF9UaW1lX0hyIDwgMTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAxNV8xNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFdmVudF9UaW1lX0hyIDwgMjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAxOF8yMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFdmVudF9UaW1lX0hyIDwgMjQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAyMV8yMyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkpKSkpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkdyb3VwMF8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAzXzUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDZfOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwOV8xMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMTJfMTQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDE1XzE3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAxOF8yMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMjFfMjMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICkKCnJtKEFsbERheXNfRmlyc3RTdG9wSUQpCnN0cihBbGxEYXlzX0FkZFZhcnMpCgoKIyBncm91cF9ieShBbGxEYXlzX0FkZFZhcnMsCiMgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwCiMgICAgICAgICApICU+JSAKIyAgIHN1bW1hcmlzZShDbnRzID0gbigpCiMgICAgICAgICAgICApCgoKIyBWaWV3KGhlYWQoZmlsdGVyKEFsbERheXNfQWRkVmFycywKIyAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHIgPT0gMAojICAgICAgICAgICAgICAgICApLAojICAgICAgICAgICA1MAojICAgICAgICAgICkKIyAgICAgKQoKIyBWaWV3KGhlYWQoQWxsRGF5c19BZGRWYXJzLCA1MCkpCgpgYGAKCgo8IS0tIEZ1bmN0aW9uIGZvciBjYWxjdWxhdGluZyB0aGUgZGlzdGFuY2UgdHJhdmVsZWQgYmFzZWQgb24gdGhlIEhhdmVyc2luZSBmb3JtdWxhLiAgT3JpZ2luYWwgY29kZSBmcm9tOiBodHRwczovL3d3dy5yLWJsb2dnZXJzLmNvbS9ncmVhdC1jaXJjbGUtZGlzdGFuY2UtY2FsY3VsYXRpb25zLWluLXIvIC0tPgo8IS0tIGBgYHtyfSAtLT4KCjwhLS0gZ2NkLmhmIDwtIGZ1bmN0aW9uKGxvbmcxLCBsYXQxLCBsb25nMiwgbGF0MikgeyAtLT4KPCEtLSAgIFIgPC0gNjM3MSAjIEVhcnRoIG1lYW4gcmFkaXVzIFtrbV0gLS0+CjwhLS0gICBkZWx0YS5sb25nIDwtIChsb25nMiAtIGxvbmcxKSAtLT4KPCEtLSAgIGRlbHRhLmxhdCA8LSAobGF0MiAtIGxhdDEpIC0tPgo8IS0tICAgYSA8LSBzaW4oZGVsdGEubGF0LzIpXjIgKyBjb3MobGF0MSkgKiBjb3MobGF0MikgKiBzaW4oZGVsdGEubG9uZy8yKV4yIC0tPgo8IS0tICAgYyA8LSAyICogYXNpbihtaW4oMSxzcXJ0KGEpKSkgLS0+CjwhLS0gICBkID0gUiAqIGMgKiAwLjYyMTM3MSAjIDEga20gPSAwLjYyMTM3MSBtaWxlcyAtLT4KPCEtLSAgIHJldHVybihkKSAjIERpc3RhbmNlIGluIG1pbGVzIC0tPgo8IS0tIH0gLS0+Cgo8IS0tIGBgYCAtLT4KCgpGZWF0dXJlIGVuZ2luZWVyaW5nLgoKQ3JlYXRpbmcgbW9yZSB2YXJpYWJsZXMuIENyZWF0aW5nIGEgQnVzRXZlbnQgcm93IG51bWJlciBmb3IgZnV0dXJlIGlkZW50aWZpY2F0aW9uIHB1cnBvc2VzLiBUaGVuLCBjcmVhdGluZyB2YXJpb3VzIHZhcmlhYmxlcyB0byBhbmFseXplIGRpc3RhbmNlIHRyYXZlbGVkIGFuZCBzcGVlZC4KYGBge3J9CgpBbGxEYXlzX0J1c0RheSA8LSBncm91cF9ieShBbGxEYXlzX0FkZFZhcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c19JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKEJ1c0RheV9FdmVudE51bSA9IHJvd19udW1iZXIoKSwgICMgdXNlZCB0byBpZGVudGlmeSBCdXMgbW92ZW1lbnRzIG9uIGEgcGFydGljdWxhciBkYXRlCiAgICAgICAgIAogICAgICAgICBSb3V0ZV9MYWcxID0gbGFnKFJvdXRlKSwgICMgdXNlZCBpbiBmdXR1cmUgYW5hbHlzZXMgdG8gaWRlbnRpZnkgUm91dGUgY2hhbmdlcwogICAgICAgICBSb3V0ZUFsdF9MYWcxID0gbGFnKFJvdXRlQWx0KSwgICMgdXNlZCBpbiBmdXR1cmUgYW5hbHlzZXMgdG8gaWRlbnRpZnkgUm91dGVBbHQgKGRpcmVjdGlvbikgY2hhbmdlcwogICAgICAgICAKICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSA9IGxhZyhPZG9tZXRlcl9EaXN0YW5jZSksCiAgICAgICAgIAogICAgICAgICBMYXRpdHVkZV9MMSA9IGxhZyhMYXRpdHVkZSksCiAgICAgICAgIExvbmdpdHVkZV9MMSA9IGxhZyhMb25naXR1ZGUpLAogICAgICAgICAjIExhdF9SYWRpYW4gPSBMYXRpdHVkZSpwaS8xODAsCiAgICAgICAgICMgTG9uZ19SYWRpYW4gPSBMb25naXR1ZGUqcGkvMTgwLAogICAgICAgICAjIExhdF9SYWRpYW5fTDEgPSBsYWcoTGF0X1JhZGlhbiksCiAgICAgICAgICMgTG9uZ19SYWRpYW5fTDEgPSBsYWcoTG9uZ19SYWRpYW4pLAogICAgICAgICAKICAgICAgICAgIyBhY2NvdW50aW5nIGZvciBwb3RlbnRpYWwgbmVnYXRpdmUgZGlzdGFuY2VzCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX0Z0ID0gaWZlbHNlKE9kb21ldGVyX0Rpc3RhbmNlID4gT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2UgLSBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID0gVHJhdmVsRGlzdGFuY2VfRnQgLyA1MjgwLCAjNSwyODAgZmVldCBpbiAxIG1pbGUKICAgICAgICAgCiAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWkyID0gZ2NkLmhmKGxvbmcxID0gTG9uZ19SYWRpYW5fTDEsCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdDEgPSBMYXRfUmFkaWFuX0wxLAogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb25nMiA9IExvbmdfUmFkaWFuLAogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXQyID0gTGF0X1JhZGlhbgogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzID0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaWZlbHNlKChpcy5uYShMb25naXR1ZGVfTDEpIHwgaXMubmEoTGF0aXR1ZGVfTDEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKGNiaW5kKExvbmdpdHVkZV9MMSwgTGF0aXR1ZGVfTDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNiaW5kKExvbmdpdHVkZSwgTGF0aXR1ZGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICogMC4wMDA2MjEzNzEsICMgMC4wMDA2MjEzNzEgbWlsZXMgPSAxIG1ldGVyCiAgICAgICAgIAogICAgICAgICAjIGFjY291bnRpbmcgZm9yIHBvdGVudGlhbCBuZWdhdGl2ZSB0aW1lcwogICAgICAgICBUcmF2ZWxUaW1lX1NlYyA9IGFzLm51bWVyaWMoaWZlbHNlKEV2ZW50X1RpbWUgPiBsYWcoRGVwYXJ0dXJlX1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWUgLSBsYWcoRGVwYXJ0dXJlX1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRyYXZlbFRpbWVfSHIgPSBUcmF2ZWxUaW1lX1NlYyAvIDM2MDAsICMgMyw2MDAgc2Vjb25kcyBpbiAxIGhvdXIKICAgICAgICAgCiAgICAgICAgICMgYWNjb3VudGluZyBmb3IgcG90ZW50aWFsIG5lZ2F0aXZlIG9yIHplcm8gdHJhdmVsIHRpbWVzCiAgICAgICAgIFNwZWVkQXZnX01waCA9IGlmZWxzZShUcmF2ZWxUaW1lX0hyID4gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pIC8gVHJhdmVsVGltZV9IciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIAogICAgICAgICBTdGFydF9JRCA9IGxhZyhTdG9wSURfQ2xlYW4pLAogICAgICAgICBTdGFydF9EZXNjID0gbGFnKFN0b3BfRGVzYyksCiAgICAgICAgIFN0YXJ0U3RvcF9JRCA9IGlmZWxzZShpcy5uYShTdGFydF9JRCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiTlVMTCIsIFN0b3BJRF9DbGVhbiwgc2VwID0gIi0tIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZShTdGFydF9JRCwgU3RvcElEX0NsZWFuLCBzZXAgPSAiLS0iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpCgoKcm0oQWxsRGF5c19BZGRWYXJzKQpzdHIoQWxsRGF5c19CdXNEYXkpCgojIHN1bW1hcnkoQWxsRGF5c19CdXNEYXkpCgojIFZpZXcodGFpbChBbGxEYXlzX0J1c0RheSwgNTApKQoKYGBgCgoKSW5zcGVjdGluZyBmb3IgaXNzdWVzIHdpdGggU3RhcnRTdG9wX0lEICh3aGVyZSB0aGUgdmFsdWUgaXMgZWl0aGVyIE5BIG9yIGNvbnRhaW5zIE5VTEwpLiBUaGV5IE9OTFkgZXhpc3Qgd2hlbiBCdXNEYXlfRXZlbnROdW0gPSAxICh3aGljaCBpcyBieSBkZXNpZ24pLiBTbyBldmVyeXRoaW5nIGxvb2tzIE9LLgpgYGB7cn0KClZpZXcoZ3JvdXBfYnkoQWxsRGF5c19CdXNEYXksCiAgICAgICAgICAgICAgU3RhcnRTdG9wX0lECiAgICAgICAgICAgICApICU+JSAKICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgQ250ID0gbigpCiAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhDbnQpCiAgICAgICAgICAgICAgKQogICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19CdXNEYXksCiAgICAgICAgICAgIChpcy5uYShTdGFydFN0b3BfSUQpIHwKICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFN0YXJ0U3RvcF9JRCwgIk5VTEwiKQogICAgICAgICAgICApICYKICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICkKICAgICkKCmBgYAoKClN0YXRzIChxdWFudGlsZXMpIG92ZXJhbGwgZm9yIFRyYXZlbERpc3RhbmNlX01pLgpgYGB7cn0KClF1YW50aWxlc19kdCA8LSBBbGxEYXlzX0J1c0RheSAlPiUgCiAgbXV0YXRlKFREX01pX3EyID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuMDIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX3E5OCA9IHF1YW50aWxlKHggPSBUcmF2ZWxEaXN0YW5jZV9NaSwgcHJvYnMgPSAwLjk4LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfcTIgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9TZWMsIHByb2JzID0gMC4wMiwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX3E5OCA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjk4LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9xMiA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuMDIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX3E5OCA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuOTgsIG5hLnJtID0gVFJVRSkKICAgICAgICApICU+JSAKICBkYXRhLnRhYmxlKCkKCgpTdGF0cyA8LSBRdWFudGlsZXNfZHQgJT4lIAogIG11dGF0ZShURF9NaV9NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfTWVhbl9GID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaVtURF9NaV9xMiA8PSBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pIDw9IFREX01pX3E5OF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX01lZF9GID0gbWVkaWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX3EyIDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pW1REX01pX3EyIDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfcTk4XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgCiAgICAgICAgIFRUX1NlY19NZWFuID0gbWVhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX01lYW5fRiA9IG1lYW4oVHJhdmVsVGltZV9TZWNbVFRfU2VjX3EyIDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX3E5OF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19NZWQgPSBtZWRpYW4oVHJhdmVsVGltZV9TZWMsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfcTIgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUVF9TZWNfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykKICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9TZWNbVFRfU2VjX3EyIDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX3E5OF0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCgogICAgICAgICBUVF9Icl9NZWFuID0gbWVhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9NZWFuX0YgPSBtZWFuKFRyYXZlbFRpbWVfSHJbVFRfSHJfcTIgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyW1RUX0hyX3EyIDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX3E5OF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX0NudCA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcikKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfSHJbVFRfSHJfcTIgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfcTk4XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkgJT4lIAogIGRhdGEuZnJhbWUoKQoKcm0oQWxsRGF5c19CdXNEYXkpCnJtKFF1YW50aWxlc19kdCkKc3RyKFN0YXRzKQojIFZpZXcoaGVhZChTdGF0cywgNTApKQoKYGBgCgoKU3RhdHMgZm9yIFN0YXJ0U3RvcF9JRC4KYGBge3J9CgpRdWFudGlsZXNfU1NfZHQgPC0gZ3JvdXBfYnkoU3RhdHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFREX01pX1NTX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxEaXN0YW5jZV9NaSwgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfU1NfcTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9TZWMsIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU19xNSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSkKICAgICAgICApICU+JSAKICBkYXRhLnRhYmxlKCkKCgpTdGF0c19TdFN0IDwtIGdyb3VwX2J5KFF1YW50aWxlc19TU19kdCwKICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQKICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShURF9NaV9TU19NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NfTWVhbl9GID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaVtURF9NaV9TU19xNSA8PSBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pIDw9IFREX01pX1NTX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9TU19NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTX01lZF9GID0gbWVkaWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfU1NfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfU1NfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NfcTk1XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgCiAgICAgICAgIFRUX1NlY19TU19NZWFuID0gbWVhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTX01lYW5fRiA9IG1lYW4oVHJhdmVsVGltZV9TZWNbVFRfU2VjX1NTX3E1IDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX1NTX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19TU19NZWQgPSBtZWRpYW4oVHJhdmVsVGltZV9TZWMsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfU1NfcTUgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUVF9TZWNfU1NfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykpLAogICAgICAgICBUVF9TZWNfU1NfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfU2VjW1RUX1NlY19TU19xNSA8PSBUcmF2ZWxUaW1lX1NlYyAmIFRyYXZlbFRpbWVfU2VjIDw9IFRUX1NlY19TU19xOTVdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCgogICAgICAgICBUVF9Icl9TU19NZWFuID0gbWVhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU19NZWFuX0YgPSBtZWFuKFRyYXZlbFRpbWVfSHJbVFRfSHJfU1NfcTUgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyW1RUX0hyX1NTX3E1IDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX1NTX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTX0NudCA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcikpLAogICAgICAgICBUVF9Icl9TU19DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcltUVF9Icl9TU19xNSA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9TU19xOTVdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUgCiAgZGF0YS5mcmFtZSgpCgpybShTdGF0cykKcm0oUXVhbnRpbGVzX1NTX2R0KQpzdHIoU3RhdHNfU3RTdCkKIyBWaWV3KGhlYWQoU3RhdHNfU3RTdCwgNTApKQoKYGBgCgoKU3RhdHMgZm9yIFN0YXJ0U3RvcF9JRCB3aXRoIEV2ZW50X1RpbWVfSHJHcm91cC4KYGBge3J9CgpRdWFudGlsZXNfU1NIR19kdCA8LSBncm91cF9ieShTdGF0c19TdFN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHJHcm91cAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShURF9NaV9TU0hHX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTSEdfcTk1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU0hHX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfU2VjLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU0hHX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU0hHX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfSHIsIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfSHJfU1NIR19xOTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9IciwgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpCiAgICAgICAgKSAlPiUgCiAgZGF0YS50YWJsZSgpCgoKU3RhdHNfU3RTdF9IckdycCA8LSBncm91cF9ieShRdWFudGlsZXNfU1NIR19kdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoVERfTWlfU1NIR19NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NIR19NZWFuX0YgPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTSEdfcTUgPD0gVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaSA8PSBURF9NaV9TU0hHX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfU1NIR19NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTSEdfTWVkX0YgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWlbVERfTWlfU1NIR19xNSA8PSBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pIDw9IFREX01pX1NTSEdfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFREX01pX1NTSEdfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9TU0hHX0NudF9GID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaVtURF9NaV9TU0hHX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NIR19xOTVdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgCiAgICAgICAgIFRUX1NlY19TU0hHX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfU2VjLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfU1NIR19NZWFuX0YgPSBtZWFuKFRyYXZlbFRpbWVfU2VjW1RUX1NlY19TU0hHX3E1IDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX1NTSEdfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19TU0hHX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTSEdfTWVkX0YgPSBtZWRpYW4oVHJhdmVsVGltZV9TZWNbVFRfU2VjX1NTSEdfcTUgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfU1NIR19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUVF9TZWNfU1NIR19DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSksCiAgICAgICAgIFRUX1NlY19TU0hHX0NudF9GID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfU1NIR19xNSA8PSBUcmF2ZWxUaW1lX1NlYyAmIFRyYXZlbFRpbWVfU2VjIDw9IFRUX1NlY19TU0hHX3E5NV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCgogICAgICAgICBUVF9Icl9TU0hHX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTSEdfTWVhbl9GID0gbWVhbihUcmF2ZWxUaW1lX0hyW1RUX0hyX1NTSEdfcTUgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfU1NIR19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTSEdfTWVkID0gbWVkaWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTSEdfTWVkX0YgPSBtZWRpYW4oVHJhdmVsVGltZV9IcltUVF9Icl9TU0hHX3E1IDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX1NTSEdfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTSEdfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX0hyKSksCiAgICAgICAgIFRUX0hyX1NTSEdfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfSHJbVFRfSHJfU1NIR19xNSA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9TU0hHX3E5NV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUgCiAgZGF0YS5mcmFtZSgpCgpybShTdGF0c19TdFN0KQpybShRdWFudGlsZXNfU1NIR19kdCkKc3RyKFN0YXRzX1N0U3RfSHJHcnApCiMgVmlldyhoZWFkKFN0YXRzX1N0U3RfSHJHcnAsIDUwKSkKCmBgYAoKCkZlYXR1cmUgZW5naW5lZXJpbmcuCgpDcmVhdGluZyBhIEJ1c0V2ZW50Um91dGUgcm93IG51bWJlciwgYW5kIGEgUm91dGVBbHRfTGFnMSBpbmRpY2F0b3IgZm9yIGZ1dHVyZSBpZGVudGlmaWNhdGlvbiBwdXJwb3Nlcy4gCmBgYHtyfQoKIyBybShRdWFudGlsZXNfZHQpCiMgcm0oUXVhbnRpbGVzX1NTX2R0KQojIHJtKEFsbERheXNfQnVzRGF5KQojIHJtKFF1YW50aWxlc19TU0hHX2R0KQojIHJtKFN0YXRzX1N0U3QpCgojIEFsbERheXNfQnVzRGF5Um91dGUgPC0gZ3JvdXBfYnkoU3RhdHNfU3RTdF9IckdycCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c19JRCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfRGF0ZSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJvdXRlCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAojICAgbXV0YXRlKFJvdXRlQWx0X0xhZzIgPSBsYWcoUm91dGVBbHQpICAjIHVzZWQgaW4gZnV0dXJlIGFuYWx5c2VzIHRvIGlkZW50aWZ5IFJvdXRlQWx0IChkaXJlY3Rpb24pIGNoYW5nZXMKIyAgICAgICAgICAKIyAgICAgICAgICAjIE9kb21ldGVyX0Rpc3RhbmNlX0xhZzEgPSBsYWcoT2RvbWV0ZXJfRGlzdGFuY2UpLAojICAgICAgICAgICMgCiMgICAgICAgICAgIyAjIGFjY291bnRpbmcgZm9yIHBvdGVudGlhbCBuZWdhdGl2ZSBkaXN0YW5jZXMKIyAgICAgICAgICAjIFRyYXZlbERpc3RhbmNlX0Z0ID0gaWZlbHNlKE9kb21ldGVyX0Rpc3RhbmNlID49IE9kb21ldGVyX0Rpc3RhbmNlX0xhZzEsCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZSAtIE9kb21ldGVyX0Rpc3RhbmNlX0xhZzEsCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQQojICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICApLAojICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWkgPSBUcmF2ZWxEaXN0YW5jZV9GdCAvIDUyODAsICM1LDI4MCBmZWV0IGluIDEgbWlsZQojICAgICAgICAgICMgCiMgICAgICAgICAgIyAjIGFjY291bnRpbmcgZm9yIHBvdGVudGlhbCBuZWdhdGl2ZSB0aW1lcwojICAgICAgICAgICMgVHJhdmVsVGltZV9TZWMgPSBhcy5udW1lcmljKGlmZWxzZShFdmVudF9UaW1lID49IGxhZyhEZXBhcnR1cmVfVGltZSksCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWUgLSBsYWcoRGVwYXJ0dXJlX1RpbWUpLAojICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQQojICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiMgICAgICAgICAgIyBUcmF2ZWxUaW1lX0hyID0gVHJhdmVsVGltZV9TZWMgLyAzNjAwLCAjIDMsNjAwIHNlY29uZHMgaW4gMSBob3VyCiMgICAgICAgICAgIyAKIyAgICAgICAgICAjICMgYWNjb3VudGluZyBmb3IgcG90ZW50aWFsIG5lZ2F0aXZlIG9yIHplcm8gdHJhdmVsIHRpbWVzCiMgICAgICAgICAgIyBTcGVlZEF2Z19NcGggPSBpZmVsc2UoVHJhdmVsVGltZV9IciA+IDAsCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgLyBUcmF2ZWxUaW1lX0hyLAojICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgIE5BCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICApICU+JSAKIyAgIGRhdGEuZnJhbWUoKQojIAojIHJtKFN0YXRzX1N0U3RfSHJHcnApCiMgc3RyKEFsbERheXNfQnVzRGF5Um91dGUpCgpgYGAKCgpGZWF0dXJlIGVuZ2luZWVyaW5nLgoKQ2FsY3VsYXRpbmcgYSB2YXJpYWJsZSB0byBrbm93IGlmIHRoZSBSb3V0ZUFsdCBjaGFuZ2VkLiBDb3VsZCBiZSB1c2VmdWwgaW4gaGVscGluZyBpZGVudGlmeWluZyB3ZWlyZG5lc3MgaW4gY2FsY3VsYXRlZCBkaXN0YW5jZXMgYW5kIHNwZWVkcy4KYGBge3J9CgojIHJtKFN0YXRzX1N0U3RfSHJHcnApCgpBbGxEYXlzX0RpckNoYW5nZSA8LSBTdGF0c19TdFN0X0hyR3JwICU+JSAgIyBBbGxEYXlzX0J1c0RheVJvdXRlICU+JSAKICBtdXRhdGUoUnRlQ2hhbmdlID0gaWZlbHNlKFJvdXRlID09IFJvdXRlX0xhZzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2FtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hhbmdlIgogICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBSdGVDaGFuZ2UyID0gZmFjdG9yKGlmZWxzZShpcy5uYShSdGVDaGFuZ2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUnRlQ2hhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgRGlyQ2hhbmdlID0gaWZlbHNlKFJvdXRlQWx0ID09IFJvdXRlQWx0X0xhZzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2FtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hhbmdlIgogICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBEaXJDaGFuZ2UyID0gZmFjdG9yKGlmZWxzZShpcy5uYShEaXJDaGFuZ2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkKCiMgcm0oQWxsRGF5c19CdXNEYXlSb3V0ZSkKcm0oU3RhdHNfU3RTdF9IckdycCkKc3RyKEFsbERheXNfRGlyQ2hhbmdlKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19EaXJDaGFuZ2UsCiAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAyNTcwMDYwLCAyNTcwMDgwKQogICAgICAgICAgICkgJT4lIAogICAgICAgc2VsZWN0KC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICAgICkKICAgICkKCmBgYAoKClJlLW9yZGVyaW5nIHRoZSB2YXJpYWJsZXMgdG8gZWFzZSB3aXRoIGNvbXByZWhlbnNpb24uCmBgYHtyfQoKQWxsRGF5c19OZXdPcmRlciA8LSAgc2VsZWN0KEFsbERheXNfRGlyQ2hhbmdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUm93TnVtX09HLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVW5pcXVlTGF0TG5nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSb3V0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJ0ZUNoYW5nZTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSb3V0ZUFsdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUm91dGVBbHRfTGFnMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIERpckNoYW5nZTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSb3V0ZV9EaXJlY3Rpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wX1NlcXVlbmNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RhcnRfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydF9EZXNjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBTdG9wX0lELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcElEX0NsZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcElEX0luZGljYXRvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BfRGVzYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnlDb2RlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9TdGF0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BfQ291bnR5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9DaXR5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9aaXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UeXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfRGVzY3JpcHRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX1lyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9NdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0RhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0RheSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX01pbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZXBhcnR1cmVfVGltZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIER3ZWxsX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEd2VsbF9UaW1lMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMYXRpdHVkZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvbmdpdHVkZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhlYWRpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9kb21ldGVyX0Rpc3RhbmNlX0xhZzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX0Z0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfcTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9xOTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19xNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX3E5NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX3E5NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX3EyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX3E5OCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19xNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19xOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19xNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU0hHX3E5NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU0hHX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfTWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU0hHX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU0hHX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX0NudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfSHIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9xMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX3E5OCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX3E1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NfcTk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19xNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTSEdfcTk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NfTWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NfTWVkX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTSEdfTWVkX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX0NudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX0NudF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX0NudF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3BlZWRBdmdfTXBoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCnJtKEFsbERheXNfRGlyQ2hhbmdlKQpzdHIoc2VsZWN0KEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgKQogICApCnN0cihBbGxEYXlzX05ld09yZGVyKQoKIyBWaWV3KGhlYWQoQWxsRGF5c19OZXdPcmRlciwgNTAwKSkKIyBWaWV3KHRhaWwoQWxsRGF5c19OZXdPcmRlciwgNTAwKSkKCmBgYAoKClN1bW1hcml6aW5nIHRoZSBkYXRhIHRvIGhlbHAgc3BvdCBhbm9tb2xpZXMuCmBgYHtyfQoKVmlldyhncm91cF9ieShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgIFN0b3BfQ2l0eSkgJT4lIAogICAgICAgc3VtbWFyaXNlKENudF9OdW0gPSBuKCksCiAgICAgICAgICAgICAgICAgQ250X1BjdCA9IDEwMCpDbnRfTnVtIC8gKG5yb3coQWxsRGF5c19OZXdPcmRlcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhDbnRfTnVtKSkKKQoKc3VtbWFyeShBbGxEYXlzX05ld09yZGVyKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaS4KClZpZXcoVHJhdkRpc3RNaV9QY3RpbGVzKTogOTklIG9mIFRyYXZlbERpc3RhbmNlX01pIGFyZSBhYm91dCAxIG1pbGUgb3IgbGVzcy4uLmJ1dCBzb21lIHdlaXJkIFRyYXZlbERpc3RhbmNlX01pIHZhbHVlcyAoZS5nLiwgNTg0IG1pbGVzIHRyYXZlbGVkKSBleGlzdC4KYGBge3J9CgpUcmF2RGlzdE1pX050aWxlIDwtIGFzLmRhdGEuZnJhbWUoQWxsRGF5c19OZXdPcmRlciRUcmF2ZWxEaXN0YW5jZV9NaSkgJT4lIAogIG11dGF0ZSgjUGN0aWxlID0gbnRpbGUoQWxsRGF5c19OZXdPcmRlciRUcmF2ZWxEaXN0YW5jZV9NaSwgMTAwKSwKICAgICAgICAgI01pblIgPSBtaW5fcmFuayhBbGxEYXlzX05ld09yZGVyJFRyYXZlbERpc3RhbmNlX01pKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld09yZGVyJFRyYXZlbERpc3RhbmNlX01pKSwKICAgICAgICAgUGN0Ul9Sb3VuZCA9IHJvdW5kKFBjdFIsIDIpCiAgICAgICAgKSAKCmNvbG5hbWVzKFRyYXZEaXN0TWlfTnRpbGUpWzFdIDwtICJUcmF2ZWxEaXN0YW5jZV9NaSIKIyBzdHIoVHJhdkRpc3RNaV9OdGlsZSkKClRyYXZEaXN0TWlfTnRpbGVfUm93cyA8LSBucm93KFRyYXZEaXN0TWlfTnRpbGUpCgojIFZpZXcodGFpbChUcmF2RGlzdE1pX050aWxlLCA1MDApKQoKClRyYXZEaXN0TWlfUGN0aWxlcyA8LSBncm91cF9ieShUcmF2RGlzdE1pX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGN0Ul9Sb3VuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5UcmF2RGlzdE1pQXRQY3RpbGUgPSBtaW4oVHJhdmVsRGlzdGFuY2VfTWkpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gVHJhdkRpc3RNaV9OdGlsZV9Sb3dzCiAgKSAlPiUgCiAgbXV0YXRlKEN1bVN1bVBBdFAgPSBjdW1zdW0oUGN0c0F0UGN0aWxlKQogICAgICAgICkKCnJtKFRyYXZEaXN0TWlfTnRpbGUpCnJtKFRyYXZEaXN0TWlfTnRpbGVfUm93cykKClZpZXcoVHJhdkRpc3RNaV9QY3RpbGVzKQpUcmF2RGlzdE1pX1BjdGlsZXMKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkuCgpXaHkgYXJlIHNvbWUgVHJhdmVsRGlzdGFuY2VfTWkgIk5BIj8gSXQgbG9va3MgbGlrZSBwYXJ0aWFsbHkgYmVjYXVzZSB0aGUgcmVjb3JkcyBhcmUgdGhlIGZpcnN0IHRyaXAgb2YgdGhlIGRheSAoZm9yIHRoYXQgYnVzKSwgc28gSSBwdXJwb3NlZnVsbHkgc2V0IHRoZSBkaXN0YW5jZSB0byAiTkEiLiBBbm90aGVyIHJlYXNvbiBpcyBkdWUgdG8gdGhlIG9kb21ldGVyIHJlY29yZGluZyBhIHZhbHVlIGxlc3MgdGhhbiB0aGUgcHJldmlvdXMgb2RvbWV0ZXIgcmVjb3JkaW5nLiBJbiBtb3N0IGNhc2VzLCBJIGhhdmUgbm8gZXhwbGFuYXRpb24gZm9yIHRoaXMgLSB0aG91Z2ggSSBoYXZlIG9ic2VydmVkIGFib3V0IDY3JSBvZiBhbGwgaW5zdGFuY2VzIHdoZXJlIFRyYXZlbERpc3RhbmNlX01pIGlzIE5BIChvdGhlciB0aGFuIGJlY2F1c2UgaXQncyB0aGUgZmlyc3QgcmVjb3JkIG9mIHRoZSBkYXkpIGFyZSBpbnN0YW5jZXMgd2hlcmUgRGlyQ2hhbmdlMiBpcyAiQ2hhbmdlIi4gVGhpcyBpcyB3ZWlyZCBhbmQgc2hvdWxkIGJlIGFza2VkIHRvIFdNQVRBLgpgYGB7cn0KCiMgVmlldyhoZWFkKEFsbERheXNfTmV3T3JkZXIsIDUwMCkpCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMSAjIFdoZW4gQnVzRGF5X0V2ZW50TnVtID09IDEsIFRyYXZlbERpc3RhbmNlX01pIGlzIE5BIGJ5IGRlc2lnbiAoZG9uJ3Qgd2FudCB0byBjYWxjdWxhdGUgZGlzdGFuY2UgYmFzZWQgb24geWVzdGVyZGF5J3MgcG9zaXRpb24pCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBncm91cF9ieShTdGFydFN0b3BfSUQpICU+JSAKICAgICAgIHN1bW1hcmlzZShDbnRzID0gc3VtKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhDbnRzKQogICAgICAgICAgICAgICkKICAgICkKClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCA9PSAiMTAwMDI0NS0tMTAwMDIxMSIKICAgICAgICAgICApICU+JSAKICAgICAgIHNlbGVjdChSb3dOdW1fT0csCiAgICAgICAgICAgICAgU3RhcnRTdG9wX0lELAogICAgICAgICAgICAgIEV2ZW50X1RpbWUsCiAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwLAogICAgICAgICAgICAgIEJ1c19JRCwKICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzLAogICAgICAgICAgICAgIFREX01pX1NTX01lYW4sCiAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbl9GLAogICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbiwKICAgICAgICAgICAgICBURF9NaV9TU0hHX01lYW5fRiwKICAgICAgICAgICAgICBURF9NaV9TU19NZWQsCiAgICAgICAgICAgICAgVERfTWlfU1NfTWVkX0YsCiAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWQsCiAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWRfRiwKICAgICAgICAgICAgICBURF9NaV9TU19DbnQsCiAgICAgICAgICAgICAgVERfTWlfU1NfQ250X0YsCiAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnQsCiAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRgogICAgICAgICAgICAgICkgJT4lIAogICAgICAgbXV0YXRlKFJhdGlvX01lYW5Ub0h2cnMgPSBURF9NaV9TU19NZWFuIC8gVHJhdmVsRGlzdGFuY2VfTWlfSHZycykgJT4lIAogICAgICAgYXJyYW5nZShFdmVudF9UaW1lKQogICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgKQogICAgKQoKIyBUaGVzZSByZWNvcmRzIGFyZSBOQSBiZWN1YXNlIHRoZSByZWNvcmQgaXMgdGhlIGZpcnN0IHJlY29yZCBvZiB0aGUgZGF5ICh0aGUgRXZlbnRfVGltZV9EYXRlKQpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMzI2LCAzNDYpIHwgIyAzMzYKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNTkxLCA2MTEpIHwgIyA2MDEKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgODQ1LCA4NjUpICMgODU1CiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaS4KClRoZXNlIHJlY29yZHMgYXJlIE5BIGJlY3Vhc2UgdGhlIGN1cnJlbnQgcmVjb3JkIG9kb21ldGVyIGlzIGxlc3MgdGhhbiB0aGUgcHJldmlvdXMgcmVjb3JkIG9kb21ldGVyLiBUaGVvcmV0aWNhbGx5LCB0aGlzIHNob3VsZCBOT1QgaGFwcGVuLiBNZTogaXQgYXBwZWFycyB0aGF0IGFib3V0IDY3JSBvZiBhbGwgaW5zdGFuY2VzIHdoZXJlIFRyYXZlbERpc3RhbmNlX01pIGlzIE5BIChvdGhlciB0aGFuIGJlY2F1c2UgaXQncyB0aCBmaXJzdCByZWNvcmQgb2YgdGhlIGRheSkgYXJlIGluc3RhbmNlcyB3aGVyZSBEaXJDaGFuZ2UyIGlzICJDaGFuZ2UiLiBUaGlzIGlzIHdlaXJkIGFuZCBzaG91bGQgYmUgYXNrZWQgdG8gV01BVEEuCmBgYHtyfQoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDE5NCwgMjE0KSB8ICMgMjA0CiAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ0MCwgNDYwKSB8ICMgNDUwCiAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ3OCwgNDk4KSB8ICMgNDg4CiAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDUxMCwgNTMwKSAjIDUyMAogICAgICAgICAgICkKICAgICkKClRlc3RUYWJsZSA8LSBmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFRyYXZlbERpc3RhbmNlX05BID0gYXMuZmFjdG9yKGlmZWxzZShpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVHJ1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFsc2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUKICBncm91cF9ieShEaXJDaGFuZ2UyLCBUcmF2ZWxEaXN0YW5jZV9OQSkgJT4lCiAgc3VtbWFyaXNlKFRyYXZEaXN0TWlfTkFDbnRzID0gbigpCiAgICAgICAgICAgKQoKIyBUZXN0VGFibGUKClRlc3RUYWJsZV9TcHJlYWQgPC0gYXMuZGF0YS5mcmFtZShzcHJlYWQoVGVzdFRhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX05BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZEaXN0TWlfTkFDbnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHNlbGVjdChGYWxzZSwKICAgICAgICAgVHJ1ZQogICAgICAgICkKCnJvdy5uYW1lcyhUZXN0VGFibGVfU3ByZWFkKSA8LSBjKCJDaGFuZ2UiLCAiU2FtZSIpCiMgc3RyKFRlc3RUYWJsZV9TcHJlYWQpCiMgVGVzdFRhYmxlX1NwcmVhZAoKcHJvcC50YWJsZShhcy50YWJsZShhcy5tYXRyaXgoVGVzdFRhYmxlX1NwcmVhZCkKICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgMQogICAgICAgICAgKQoKcHJvcC50YWJsZShhcy50YWJsZShhcy5tYXRyaXgoVGVzdFRhYmxlX1NwcmVhZCkKICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgMgogICAgICAgICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaS4KCkxldCdzIGxvb2sgYXQganVzdCB0aGUgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIE5PVCAiTkEiLgpgYGB7cn0KCnJtKFRlc3RUYWJsZSwgVGVzdFRhYmxlX1NwcmVhZCkKClRyYXZlbERpc3RhbmNlX01pX05vTkEgPC0gZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWkgIT0gMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpkaW0oQWxsRGF5c19OZXdPcmRlcikKZGltKFRyYXZlbERpc3RhbmNlX01pX05vTkEpCm5yb3coQWxsRGF5c19OZXdPcmRlcikgLSBucm93KFRyYXZlbERpc3RhbmNlX01pX05vTkEpCgpzdHIoVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSkKc3VtbWFyeShUcmF2ZWxEaXN0YW5jZV9NaV9Ob05BKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaS4KCkxldCdzIHBsb3QganVzdCB0aGUgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIE5PVCAiTkEiLgpgYGB7cn0KClRyYXZEaXN0TWlfSGlzdERlbiA8LSBnZ3Bsb3Qoc2VsZWN0KFRyYXZlbERpc3RhbmNlX01pX05vTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gLi5kZW5zaXR5Li4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDUsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3VyID0gImdyZXk2MCIsIHNpemUgPSAwLjIpICsKICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgY29sb3VyID0gInJlZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMS41KSwgeWxpbSA9IGMoMCwgNC4wKQogICAgICAgICAgICAgICAgICkgKwogIGxhYnModGl0bGUgPSAiVmFyaWF0aW9uIGluIERpc3RhbmNlIEJldHdlZW4gU3RvcHMiLAogICAgICAgeCA9ICJUcmF2ZWwgRGlzdGFuY2UgKG1pbGVzKSIsCiAgICAgICB5ID0gIkRlbnNpdHkiCiAgICAgICkKClRyYXZEaXN0TWlfSGlzdERlbgoKYGBgCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKTG9va2luZyBhdCB0aGUgZXh0cmVtZWx5IGxhcmdlIFRyYXZlbERpc3RhbmNlX01pIHZhbHVlcy4gU29tZSAoYXByb3ggMjclKSBvZiBUcmF2ZWxEaXN0YW5jZV9NaSB2YWx1ZXMgPiAxIG1pbGUgYXJlIHdoZW4gdGhlIERpckNoYW5nZTIgY2hhbmdlcy4uLmJ1dCB3aGF0IGFib3V0IHRoZSBvdGhlciB+NzMlPwpgYGB7cn0KCnJtKFRyYXZlbERpc3RhbmNlX01pX05vTkEpCgojIGV4YW1wbGVzIG9mIHdlaXJkbHkgbGFyZ2UgVHJhdmVsRGlzdGFuY2VfTWkKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiAxLjE1ODcxMjEyMTIgIyAxLjE1ODcxMjEyMTIgaXMgdGhlIDk5dGggcGVyY2VudGlsZQogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShkZXNjKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICkKICAgICkKCgojIFdoeSBhcmUgdGhlc2UgZXh0cmVtZXM/ICBBaXJwb3J0cz8gIEJ1cyBjb2xsZWN0aW9uIHBvaW50cz8KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0MDQ0LCA0OTQwNjQpIHwgIyA0OTQwNTQKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0MjczLCA0OTQyOTMpIHwgIyA0OTQyODMKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0NjI2LCA0OTQ2NDYpIHwgIyA0OTQ2MzYKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMTYxMDE1NiwgMTYxMDE3NikgfCAjIDE2MTAxNjYKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMjA3MzA3NCwgMjA3MzA5NCkgIyAyMDczMDg0CiAgICAgICAgICAgKQogICAgKQoKIyBCZWZvcmUgUmVtb3ZpbmcgUnVucwojIFZpZXcoZmlsdGVyKEFsbERheXNfU29ydGVkLAojICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQwNDQsIDQ5NDA2NCkgfCAjIDQ5NDA1NAojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ5NDI3MywgNDk0MjkzKSB8ICMgNDk0MjgzCiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0NjI2LCA0OTQ2NDYpIHwgIyA0OTQ2MzYKIyAgICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAxNjEwMTU2LCAxNjEwMTc2KSB8ICMgMTYxMDE2NgojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDIwNzMwNzQsIDIwNzMwOTQpICMgMjA3MzA4NAojICAgICAgICAgICAgKQojICAgICApCgojIEFmdGVyIFJlbW92aW5nIFJ1bnMKIyBWaWV3KGZpbHRlcihBbGxEYXlzX0ZpcnN0U3RvcElELAojICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQwNDQsIDQ5NDA2NCkgfCAjIDQ5NDA1NAojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ5NDI3MywgNDk0MjkzKSB8ICMgNDk0MjgzCiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0NjI2LCA0OTQ2NDYpIHwgIyA0OTQ2MzYKIyAgICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAxNjEwMTU2LCAxNjEwMTc2KSB8ICMgMTYxMDE2NgojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDIwNzMwNzQsIDIwNzMwOTQpICMgMjA3MzA4NAojICAgICAgICAgICAgKQojICAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKQW55IHJlbGF0aW9uIHdpdGggRGlyQ2hhbmdlMj8gIERvZXNuJ3QgbG9vayBhcyBpZiB0aGlzIGlzIHNvLgpgYGB7cn0KCkV4dHJlbWVUcmF2RGlzdCA8LSBmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoVHJhdkRpc3RfRXh0cmVtZSA9IGlmZWxzZShUcmF2ZWxEaXN0YW5jZV9NaSA+IDEuMTU4NzEyMTIxMiwgIyAxLjE1ODcxMjEyMTIgaXMgdGhlIDk5dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUcnVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFsc2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgZ3JvdXBfYnkoRGlyQ2hhbmdlMiwgVHJhdkRpc3RfRXh0cmVtZSkgJT4lIAogIHN1bW1hcmlzZShUcmF2RGlzdE1JX0V4dENudHMgPSBuKCkKICAgICAgICAgICApCgojIEV4dHJlbWVUcmF2RGlzdAoKCkV4dHJlbWVUcmF2RGlzdF9TcHJlYWQgPC0gYXMuZGF0YS5mcmFtZShzcHJlYWQoRXh0cmVtZVRyYXZEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZEaXN0X0V4dHJlbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdkRpc3RNSV9FeHRDbnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHNlbGVjdChGYWxzZSwKICAgICAgICAgVHJ1ZQogICAgICAgICkKCnJvdy5uYW1lcyhFeHRyZW1lVHJhdkRpc3RfU3ByZWFkKSA8LSBjKCJDaGFuZ2UiLCAiU2FtZSIpCiMgc3RyKEV4dHJlbWVUcmF2RGlzdF9TcHJlYWQpCiMgRXh0cmVtZVRyYXZEaXN0X1NwcmVhZAoKcHJvcC50YWJsZShhcy50YWJsZShhcy5tYXRyaXgoRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCkKICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgMQogICAgICAgICAgKQoKcHJvcC50YWJsZShhcy50YWJsZShhcy5tYXRyaXgoRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCkKICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgMgogICAgICAgICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaS4KCkxvb2tpbmcgYXQgc3BlY2lmaWMgYnVzZXMgYW5kIFN0YXJ0U3RvcF9JRC4KYGBge3J9CgpybShFeHRyZW1lVHJhdkRpc3QsIEV4dHJlbWVUcmF2RGlzdF9TcHJlYWQpCgpWaWV3KGFycmFuZ2UoZ3JvdXBfYnkoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgIEJ1c19JRAogICAgICAgICAgICAgICAgICAgICApICU+JSAKICAgICAgICAgICAgICAgc3VtbWFyaXNlKERpc3RUcmF2X01lYW4gPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgRGlzdFRyYXZfTWVkID0gbWVkaWFuKFRyYXZlbERpc3RhbmNlX01pLCBuYS5ybSA9IFRSVUUpCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICBkZXNjKERpc3RUcmF2X01lZCkKICAgICAgICAgICAgKQogICAgKQoKCiMgZXhhbXBsZSBvZiBleHRyZW1lbHkgc21hbGwgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIChsb29rcyBsaWtlIHRoZSBvZG9tZXRlciB3YXNuJ3QgZnVuY3Rpb25pbmcpClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIEJ1c19JRCA9PSA2MTExIHwKICAgICAgICAgICAgICBCdXNfSUQgPT0gNzIwMSB8CiAgICAgICAgICAgICAgQnVzX0lEID09IDgwNTgKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoQnVzX0lELCBFdmVudF9UaW1lKQogICAgKQoKClZpZXcoYXJyYW5nZShncm91cF9ieShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgU3RhcnRTdG9wX0lECiAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogICAgICAgICAgICAgICBzdW1tYXJpc2UoRGlzdFRyYXZfTWVhbiA9IG1lYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICBEaXN0VHJhdl9NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgIGRlc2MoRGlzdFRyYXZfTWVkKQogICAgICAgICAgICApCiAgICApCgojIGV4YW1wbGUgb2YgZXh0cmVtZWx5IGxhcmdlIFRyYXZlbERpc3RhbmNlX01pIHZhbHVlcy4uLm5vIGlkZWEgd2h5Li4uClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCA9PSAiMTAwMzY2NS0tMTIiIHwKICAgICAgICAgICAgICBTdGFydFN0b3BfSUQgPT0gIjEwMDM2NjUtLTUwMDE5MjUiIHwKICAgICAgICAgICAgICBTdGFydFN0b3BfSUQgPT0gIjMwMDEwMzgtLTMwMDI1NjUiCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKFN0YXJ0U3RvcF9JRCwgRXZlbnRfVGltZSkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcuCgpJZiBUcmF2ZWxEaXNudGFjZV9NaSBpcyBiZWxvdyB0aGUgNXRoIHBlcmNlbnRpbGUgZm9yIHRoYXQgU3RhcnRTdG9wX0lELCBvciBpZiBUcmF2ZWxEaXNudGFjZV9NaSBpcyBhYm92ZSB0aGUgOTV0aCBwZXJjZW50aWxlIGZvciB0aGF0IFN0YXJ0U3RvcF9JRCwgb3IgaWYgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEgKHdoZW4gdGhlIEJ1c0RheV9FdmVudE51bSAhPTEpLCBjb25zaWRlciB0aGlzIGFuIG91dGxpZXIuICBJbiB0aGlzIGNhc2UsIHJlcGxhY2UgdGhlIHZhbHVlIHdpdGggdGhlIG1lYW4gZm9yIHRoYXQgU3RhcnRTdG9wX0lEIGFuZCBIb3VyR3JvdXAgKFREX01pX1NTSEdfTWVhbl9GKSwgb3IgaWYgdGhlcmUgYXJlIG5vdCBlbm91Z2ggdmFsdWVzIGF0IHRoZSBIb3VyR3JvdXAgbGV2ZWwsIHJlcGxhY2UgaXQgd2l0aCB0aGUgbWVhbiBmb3IgdGhhdCBTdGFydFN0b3BfSUQuCmBgYHtyfQoKIyBWaWV3KHRhaWwoQWxsRGF5c19OZXdPcmRlciwgNTAwKSkKCkFsbERheXNfTmV3VHJhdmVsRGlzdCA8LSAKICBtdXRhdGUoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3ID0gaWZlbHNlKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pIDwgVERfTWlfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gVERfTWlfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250X0YgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pIDwgVERfTWlfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gVERfTWlfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX0NudF9GID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWkgPCBURF9NaV9TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiBURF9NaV9TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX0NudCA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgIT0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgPT0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkpKSwKICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3X0xhYmVsID0gCiAgICAgICAgICAgZmFjdG9yKGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pIDwgVERfTWlfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gVERfTWlfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250X0YgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVERfTWlfU1NIR19NZWFuX0YiLAogICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxEaXN0YW5jZV9NaSA8IFREX01pX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA+IFREX01pX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX0NudF9GIDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJURF9NaV9TU19NZWFuX0YiLAogICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxEaXN0YW5jZV9NaSA8IFREX01pX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA+IFREX01pX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250ID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgIlREX01pX1NTX01lYW4iLAogICAgICAgICAgICAgICAgICBpZmVsc2UoaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgQnVzRGF5X0V2ZW50TnVtICE9IDEgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzICE9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVHJhdmVsRGlzdGFuY2VfTWlfSHZycyIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZShpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgPT0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJURF9NaV9TU19NZWFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJUcmF2ZWxEaXN0YW5jZV9NaSIKICAgICAgICAgICAgICAgICAgICAgICAgKSkpKSkKICAgICAgICAgICAgICAgICApLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzID0gaWZlbHNlKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzICE9IDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pX05ldyA8IFREX01pX3EyIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IFREX01pX3E5OAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZyc19MYWJlbCA9CiAgICAgICAgICAgZmFjdG9yKGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfSHZycykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzICE9IDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWlfTmV3IDwgVERfTWlfcTIgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgPiBURF9NaV9xOTgKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICJUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcihUcmF2ZWxEaXN0YW5jZV9NaV9OZXdfTGFiZWwpCiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICApLAogICAgICAgICBTcGVlZEF2Z19NcGhfTmV3SHZycyA9IFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMgLyBUcmF2ZWxUaW1lX0hyCiAgICAgICAgKQoKc3RyKEFsbERheXNfTmV3VHJhdmVsRGlzdCkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzICYgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LgoKUXVpY2sgc3VtbWFyeSBhbmQgdGhlbiBjb3JyZWxhdGlvbiBjYWxjdWxhdGlvbi4KYGBge3J9CgpybShBbGxEYXlzX05ld09yZGVyKQoKCiMgMzggcm93cyBtZWV0IHRoaXMgY3JpdGVyaWEgYW55bW9yZSAgLS0gIGFwcGVhcnMgdG8gYmUgdGhlIGNhc2Ugd2hlbiBib3RoIHRoZSBMYXQgTG9uZyBjYWxjdWxhdGlvbnMsIGFuZCB0aGUgVHJhdmVsRGlzdGFuY2UgY2FsY3VsYXRpb25zIGRpZCBub3QgZnVuY3Rpb24gcHJvcGVybHkuClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3KSAmCiAgICAgICAgICAgICAgQnVzRGF5X0V2ZW50TnVtICE9IDEKICAgICAgICAgICApCiAgICApCgpWaWV3KEFsbERheXNfTmV3VHJhdmVsRGlzdCAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsRGlzdGFuY2VfTWlfTmV3KSkgJT4lIAogICAgICAgaGVhZCg1MDApCiAgICApCgpzdW1tYXJ5KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICAgICApCiAgICAgICApCgpzdW1tYXJ5KHNlbGVjdChmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgQnVzRGF5X0V2ZW50TnVtICE9IDEKICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICkKICAgICAgICkKCgpjb3Ioc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzLAogICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzCiAgICAgICAgICApLAogICAgdXNlID0gInBhaXJ3aXNlLmNvbXBsZXRlLm9icyIKICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwgJiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzX0xhYmVsLgoKU2hvdyBob3cgdGhlIGxhYmVscyBjaGFuZ2VkLgpgYGB7cn0KCmdyb3VwX2J5KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3X0xhYmVsLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzX0xhYmVsCiAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKENudE51bSA9IG4oKSwKICAgICAgICAgICAgQ250UGN0ID0gZm9ybWF0KENudE51bSAvIG5yb3coQWxsRGF5c19OZXdUcmF2ZWxEaXN0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjaWVudGlmaWMgPSA5OTk5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICApICU+JSAKICBhcnJhbmdlKGRlc2MoQ250UGN0KQogICAgICAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyAmIFRyYXZlbERpc3RhbmNlX01pX05ldy4KCkdyYXBoaW5nIHRoZSB0d28gbWV0aG9kcyBvZiBjYWxjdWxhdGluZyBUcmF2ZWxEaXN0YW5jZV9NaS4KCkZpcnN0LCBsZXQncyBnZXQgY3JlYXRlIGEgZnVuY3Rpb24gdG8gcGxvdCB0aGUgbGluZXIgbW9kZWwgZXF1YXRpb24uCmBgYHtyfQoKbG1fZXFuIDwtIGZ1bmN0aW9uKGRmLCB5LCB4KXsKICBtIDwtIGxtKHkgfiB4LCBkZikKICAKICBsIDwtIGxpc3QoYSA9IGZvcm1hdChjb2VmKG0pWzFdLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgYiA9IGZvcm1hdChhYnMoY29lZihtKVsyXSksIGRpZ2l0cyA9IDIpLAogICAgICAgICAgICBzMSA9IGlmZWxzZSh0ZXN0ID0gY29lZihtKVsyXSA+IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHllcyA9ICIrIiwKICAgICAgICAgICAgICAgICAgICAgICAgbm8gPSAiLSIKICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICByMiA9IGZvcm1hdChzdW1tYXJ5KG0pJHIuc3F1YXJlZCwKICAgICAgICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMwogICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICApCiAgCiAgZXEgPC0gc3Vic3RpdHV0ZShpdGFsaWMoeSkgPT0gYX5+czF+fmIgJS4lIGl0YWxpYyh4KSoiLCJ+fml0YWxpYyhyKV4yfiI9In5yMiwKICAgICAgICAgICAgICAgICAgIGwKICAgICAgICAgICAgICAgICAgKQogIAogIGFzLmNoYXJhY3Rlcihhcy5leHByZXNzaW9uKGVxKQogICAgICAgICAgICAgICkgICAgICAgICAgICAgCn0KCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLgoKU2NhdHRlciBwbG90ICh1c2luZyBhIDEwJSBzYW1wbGUgdG8gbWFraW5nIHBsb3R0aW5nIHRpbWUgZmFzdGVyIGFuZCB0byByZWR1Y2UgdW4tbmVlZGVkIGRhdGEgaW4gdGhlICJzYW1lIiBzcGxvdCkuCmBgYHtyfQoKc2V0LnNlZWQoMTIzNDU2Nzg5KQpBbGxEYXlzX05ld1RyYXZlbERpc3RfMTBQY3QgPC0gZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgcmVuYW1lKERpc3RNZXRob2QgPSBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzX0xhYmVsKSAlPiUgCiAgc2FtcGxlX2ZyYWMoMC4xKQoKClRyYXZEaXN0X01pVnNDYWxjIDwtIGdncGxvdChzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlzdE1ldGhvZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gRGlzdE1ldGhvZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsImJsdWUiLCAiZ3JlZW4iLCAib3JhbmdlIiwgImJsYWNrIikKICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEsIGFscGhhID0gMC41KSArCiAgc2NhbGVfc2hhcGUoc29saWQgPSBGQUxTRSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9ICJibHVlIikgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgY29sb3VyID0gInJlZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMS41KSwgeWxpbSA9IGMoMCwgMS41KQogICAgICAgICAgICAgICAgICkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMS41LCAwLjI1KQogICAgICAgICAgICAgICAgICAgICkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMS41LCAwLjI1KQogICAgICAgICAgICAgICAgICAgICkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCAjYygwLjg1LCAwLjQwKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNikKICAgICAgICkgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0LAogICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBBbGxEYXlzX05ld1RyYXZlbERpc3RfMTBQY3QkVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IEFsbERheXNfTmV3VHJhdmVsRGlzdF8xMFBjdCRUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICMgeCA9IDYyLAogICAgICAgICAgICMgeSA9IDIwLAogICAgICAgICAgIHggPSAwLjcwLAogICAgICAgICAgIHkgPSAwLjAwLAogICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgY29sb3VyID0gImJsdWUiLAogICAgICAgICAgIHBhcnNlID0gVFJVRQogICAgICAgICAgKSArCiAgYW5ub3RhdGUobGFiZWwgPSAiUmVmZXJlbmNlIExpbmUgKHNsb3BlID0gMSkiLAogICAgICAgICAgICMgeCA9IDE2LAogICAgICAgICAgICMgeSA9IDMwLAogICAgICAgICAgIHggPSAwLjgwLAogICAgICAgICAgIHkgPSAxLjA1LAogICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgY29sb3VyID0gInJlZCIKICAgICAgICAgICkgKwogIGxhYnModGl0bGUgPSAiVHJhdmVsRGlzdGFuY2VfTWkgdnMuIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMiLAogICAgICAgeCA9ICJUcmF2ZWxEaXN0YW5jZV9NaSIsCiAgICAgICB5ID0gIlRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMiCiAgICAgICkKIyArCiMgICBnZW9tX2ppdHRlcigpCgpUcmF2RGlzdF9NaVZzQ2FsYwoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgJiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcuCgpHcmFwaGluZyB0ZXN0IHdpdGggcmJva2VoLgpgYGB7cn0KClRyYXZEaXN0X01pVnNDYWxjX0Jva2VoIDwtIGZpZ3VyZShkYXRhID0gc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdF8xMFBjdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERpc3RNZXRob2QKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoMCwgMS41KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlsaW0gPSBjKDAsIDEuNSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmRfbG9jYXRpb24gPSAiYm90dG9tX3JpZ2h0IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBseV9wb2ludHMoeCA9IFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICB5ID0gVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycywKICAgICAgICAgICAgY29sb3IgPSBEaXN0TWV0aG9kLAogICAgICAgICAgICBob3ZlciA9IGMoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycywgVHJhdmVsRGlzdGFuY2VfTWksIERpc3RNZXRob2QpCiAgICAgICAgICAgKSAlPiUgCiAgbHlfYWJsaW5lKGEgPSAwLCBiID0gMSwgY29sb3IgPSAicmVkIikKClRyYXZEaXN0X01pVnNDYWxjX0Jva2VoCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pX05ldy4KCkNhbGN1bGF0aW5nIHRoZSBtaW5pbXVtIFRyYXZlbERpc3RhbmNlX01pX05ldyB2YWx1ZSBhdCBlYWNoIHBlcmNlbnRpbGUuCmBgYHtyfQoKcm0oVHJhdkRpc3RfTWlWc0NhbGNfQm9rZWgpCnJtKEFsbERheXNfTmV3VHJhdmVsRGlzdF8xMFBjdCkKCgpzdW1tYXJ5KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICAgICApCiAgICAgICApCgpzdW1tYXJ5KHNlbGVjdChmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgQnVzRGF5X0V2ZW50TnVtICE9IDEKICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICkKICAgICAgICkKCgpUcmF2RGlzdE1pTl9OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3X0xhYmVsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoUGN0Ul9OID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpLAogICAgICAgICAjIFBjdFJfSCA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyksCiAgICAgICAgIFBjdFJfUm91bmRfTiA9IHJvdW5kKFBjdFJfTiwgMikKICAgICAgICAgIyBQY3RSX1JvdW5kX0ggPSByb3VuZChQY3RSX0gsIDIpCiAgICAgICAgKSAKCiMgc3RyKFRyYXZEaXN0TWlOX050aWxlKQojIFZpZXcoaGVhZChUcmF2RGlzdE1pTl9OdGlsZSwgNTAwKSkKClRyYXZEaXN0TWlOX050aWxlX1Jvd3MgPC0gbnJvdyhUcmF2RGlzdE1pTl9OdGlsZSkKCiMgVmlldyh0YWlsKFRyYXZEaXN0TWlOX050aWxlLCA1MDApKQoKClRyYXZEaXN0TWlOX1BjdGlsZXMgPC0gZ3JvdXBfYnkoVHJhdkRpc3RNaU5fTnRpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGN0Ul9Sb3VuZF9OCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5URE1pQXRQY3RpbGVfTiA9IG1pbihUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpLAogICAgIyBNaW5URE1pQXRQY3RpbGVfSCA9IG1pbihUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSwKICAgIENudHNBdFBjdGlsZV9OID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpKSwKICAgICMgQ250c0F0UGN0aWxlX0ggPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMpKSwKICAgIFBjdHNBdFBjdGlsZV9OID0gQ250c0F0UGN0aWxlX04gLyBUcmF2RGlzdE1pTl9OdGlsZV9Sb3dzCiAgICAjIFBjdHNBdFBjdGlsZV9IID0gQ250c0F0UGN0aWxlX0ggLyBUcmF2RGlzdE1pTl9OdGlsZV9Sb3dzCiAgKSAlPiUgCiAgbXV0YXRlKEN1bVN1bVBBdFBfTiA9IGN1bXN1bShQY3RzQXRQY3RpbGVfTikKICAgICAgICAgIyBDdW1TdW1QQXRQX0ggPSBjdW1zdW0oUGN0c0F0UGN0aWxlX0gpCiAgICAgICAgKQoKIyBWaWV3KFRyYXZEaXN0TWlOX1BjdGlsZXMpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKCkNhbGN1bGF0aW5nIHRoZSBtaW5pbXVtIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMgdmFsdWUgYXQgZWFjaCBwZXJjZW50aWxlLgpgYGB7cn0KClRyYXZEaXN0TWlIX050aWxlIDwtIGFzLmRhdGEuZnJhbWUoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RhcnRTdG9wX0lELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbERpc3RhbmNlX01pX05ld19MYWJlbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZyc19MYWJlbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoIyBQY3RSX04gPSBwZXJjZW50X3JhbmsoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFRyYXZlbERpc3RhbmNlX01pX05ldyksCiAgICAgICAgIFBjdFJfSCA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyksCiAgICAgICAgICMgUGN0Ul9Sb3VuZF9OID0gcm91bmQoUGN0Ul9OLCAyKSwKICAgICAgICAgUGN0Ul9Sb3VuZF9IID0gcm91bmQoUGN0Ul9ILCAyKQogICAgICAgICkgCgojIHN0cihUcmF2RGlzdE1pSF9OdGlsZSkKIyBWaWV3KGhlYWQoVHJhdkRpc3RNaUhfTnRpbGUsIDUwMCkpCgpUcmF2RGlzdE1pSF9OdGlsZV9Sb3dzIDwtIG5yb3coVHJhdkRpc3RNaUhfTnRpbGUpCgojIFZpZXcodGFpbChUcmF2RGlzdE1pSF9OdGlsZSwgNTAwKSkKCgpUcmF2RGlzdE1pSF9QY3RpbGVzIDwtIGdyb3VwX2J5KFRyYXZEaXN0TWlIX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmRfSAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgIyBNaW5URE1pQXRQY3RpbGVfTiA9IG1pbihUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpLAogICAgTWluVERNaUF0UGN0aWxlX0ggPSBtaW4oVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyksCiAgICAjIENudHNBdFBjdGlsZV9OID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpKSwKICAgIENudHNBdFBjdGlsZV9IID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSksCiAgICAjIFBjdHNBdFBjdGlsZV9OID0gQ250c0F0UGN0aWxlX04gLyBUcmF2RGlzdE1pSF9OdGlsZV9Sb3dzLAogICAgUGN0c0F0UGN0aWxlX0ggPSBDbnRzQXRQY3RpbGVfSCAvIFRyYXZEaXN0TWlIX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoIyBDdW1TdW1QQXRQX04gPSBjdW1zdW0oUGN0c0F0UGN0aWxlX04pLAogICAgICAgICBDdW1TdW1QQXRQX0ggPSBjdW1zdW0oUGN0c0F0UGN0aWxlX0gpCiAgICAgICAgKQoKIyBWaWV3KFRyYXZEaXN0TWlIX1BjdGlsZXMpCgpgYGAKCgpKb2luIFRyYXZEaXN0TWlIX1BjdGlsZXMsIFRyYXZEaXN0TWlOX1BjdGlsZXMsIGFuZCBUcmF2RGlzdE1pX1BjdGlsZXMuCgp+MTElIG9mIHJpZGVzIGFyZSBzdGlsbCBzaG93aW5nIGFzIGxlc3MgdGhhbiAwLjEgbWlsZXMgb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycy4KYGBge3J9CgpybShUcmF2RGlzdE1pTl9OdGlsZV9Sb3dzLCBUcmF2RGlzdE1pSF9OdGlsZV9Sb3dzLCBUcmF2RGlzdE1pTl9OdGlsZSwgVHJhdkRpc3RNaUhfTnRpbGUpCgoKIyBWaWV3KFRyYXZEaXN0TWlfUGN0aWxlcykKIyBWaWV3KFRyYXZEaXN0TWlOX1BjdGlsZXMpCiMgVmlldyhUcmF2RGlzdE1pSF9QY3RpbGVzKQoKVHJhdkRpc3RNaV9QY3RpbGVzX0FsbCA8LSBpbm5lcl9qb2luKHggPSBUcmF2RGlzdE1pX1BjdGlsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gVHJhdkRpc3RNaU5fUGN0aWxlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiUGN0Ul9Sb3VuZCIgPSAiUGN0Ul9Sb3VuZF9OIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgaW5uZXJfam9pbih5ID0gVHJhdkRpc3RNaUhfUGN0aWxlcywKICAgICAgICAgICAgIGJ5ID0gYygiUGN0Ul9Sb3VuZCIgPSAiUGN0Ul9Sb3VuZF9IIikKICAgICAgICAgICAgKSAlPiUgCiAgc2VsZWN0KFBjdFJfUm91bmQsCiAgICAgICAgIE1pblRyYXZEaXN0TWlBdFBjdGlsZSwKICAgICAgICAgTWluVERNaUF0UGN0aWxlX04sCiAgICAgICAgIE1pblRETWlBdFBjdGlsZV9ILAogICAgICAgICBDbnRzQXRQY3RpbGUsCiAgICAgICAgIENudHNBdFBjdGlsZV9OLAogICAgICAgICBDbnRzQXRQY3RpbGVfSCwKICAgICAgICAgUGN0c0F0UGN0aWxlLAogICAgICAgICBQY3RzQXRQY3RpbGVfTiwKICAgICAgICAgUGN0c0F0UGN0aWxlX0gsCiAgICAgICAgIEN1bVN1bVBBdFAsCiAgICAgICAgIEN1bVN1bVBBdFBfTiwKICAgICAgICAgQ3VtU3VtUEF0UF9ICiAgICAgICAgICkKCiMgc3RyKFRyYXZEaXN0TWlfUGN0aWxlc19BbGwpCgpybShUcmF2RGlzdE1pX1BjdGlsZXMsIFRyYXZEaXN0TWlOX1BjdGlsZXMsVHJhdkRpc3RNaUhfUGN0aWxlcykKCgpWaWV3KFRyYXZEaXN0TWlfUGN0aWxlc19BbGwpClRyYXZEaXN0TWlfUGN0aWxlc19BbGwKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LgoKV2h5IGFyZSB0aGVyZSBzdGlsbCBzb21lIHNtYWxsIG9yIGxhcmdlIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMgdmFsdWVzLgpgYGB7cn0KCiMgVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAojICAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKQojICAgICAgICAgICAgKSAlPiUgCiMgICAgICAgIHNlbGVjdCgtVERfTWlfcTIsCiMgICAgICAgICAgICAgICAtVERfTWlfcTk4LAojICAgICAgICAgICAgICAgLVREX01pX1NTX3E1LAojICAgICAgICAgICAgICAgLVREX01pX1NTX3E5NSwKIyAgICAgICAgICAgICAgIC1URF9NaV9TU0hHX3E1LAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfcTk1LAojICAgICAgICAgICAgICAgLVREX01pX01lYW4sCiMgICAgICAgICAgICAgICAtVERfTWlfTWVhbl9GLAojICAgICAgICAgICAgICAgLVREX01pX1NTX01lYW4sCiMgICAgICAgICAgICAgICAtVERfTWlfU1NfTWVhbl9GLAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfTWVhbiwKIyAgICAgICAgICAgICAgIC1URF9NaV9TU0hHX01lYW5fRiwKIyAgICAgICAgICAgICAgIC1URF9NaV9NZWQsCiMgICAgICAgICAgICAgICAtVERfTWlfTWVkX0YsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NfTWVkLAojICAgICAgICAgICAgICAgLVREX01pX1NTX01lZF9GLAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfTWVkLAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfTWVkX0YsCiMgICAgICAgICAgICAgICAtVERfTWlfQ250LAojICAgICAgICAgICAgICAgLVREX01pX0NudF9GLAojICAgICAgICAgICAgICAgLVREX01pX1NTX0NudCwKIyAgICAgICAgICAgICAgIC1URF9NaV9TU19DbnRfRiwKIyAgICAgICAgICAgICAgIC1URF9NaV9TU0hHX0NudCwKIyAgICAgICAgICAgICAgIC1URF9NaV9TU0hHX0NudF9GLAojICAgICAgICAgICAgICAgLVRUX1NlY19xMiwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfcTk4LAojICAgICAgICAgICAgICAgLVRUX1NlY19TU19xNSwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NfcTk1LAojICAgICAgICAgICAgICAgLVRUX1NlY19TU0hHX3E1LAojICAgICAgICAgICAgICAgLVRUX1NlY19TU0hHX3E5NSwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfTWVhbiwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfTWVhbl9GLAojICAgICAgICAgICAgICAgLVRUX1NlY19TU19NZWFuLAojICAgICAgICAgICAgICAgLVRUX1NlY19TU19NZWFuX0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTSEdfTWVhbiwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NIR19NZWFuX0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX01lZCwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfTWVkX0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTX01lZCwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NfTWVkX0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTSEdfTWVkLAojICAgICAgICAgICAgICAgLVRUX1NlY19TU0hHX01lZF9GLAojICAgICAgICAgICAgICAgLVRUX1NlY19DbnQsCiMgICAgICAgICAgICAgICAtVFRfU2VjX0NudF9GLAojICAgICAgICAgICAgICAgLVRUX1NlY19TU19DbnQsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTX0NudF9GLAojICAgICAgICAgICAgICAgLVRUX1NlY19TU0hHX0NudCwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NIR19DbnRfRiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9xMiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9xOTgsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NfcTUsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NfcTk1LAojICAgICAgICAgICAgICAgLVRUX0hyX1NTSEdfcTUsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19xOTUsCiMgICAgICAgICAgICAgICAtVFRfSHJfTWVhbiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9NZWFuX0YsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NfTWVhbiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU19NZWFuX0YsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19NZWFuLAojICAgICAgICAgICAgICAgLVRUX0hyX1NTSEdfTWVhbl9GLAojICAgICAgICAgICAgICAgLVRUX0hyX01lZCwKIyAgICAgICAgICAgICAgIC1UVF9Icl9NZWRfRiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU19NZWQsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NfTWVkX0YsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19NZWQsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19NZWRfRiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9DbnQsCiMgICAgICAgICAgICAgICAtVFRfSHJfQ250X0YsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NfQ250LAojICAgICAgICAgICAgICAgLVRUX0hyX1NTX0NudF9GLAojICAgICAgICAgICAgICAgLVRUX0hyX1NTSEdfQ250LAojICAgICAgICAgICAgICAgLVRUX0hyX1NTSEdfQ250X0YKIyAgICAgICAgICAgICAgKSAlPiUgCiMgICAgICAgIGFycmFuZ2UoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykgJT4lIAojICAgICAgICBoZWFkKDUwMCkKIyAgICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAhaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykKICAgICAgICAgICApICU+JSAKICAgICAgIHNlbGVjdCgtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykgJT4lCiAgICAgICBoZWFkKDUwMCkKICAgICkKCiMgZXhhbXBsZXMgb2YgdGhlIHNtYWxsZXN0IFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMgdmFsdWVzLgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTQyNDQ0MCAmIFJvd051bV9PRyA8PSAxNDI0NDYwKSB8ICMgMTQyNDQ1MCAgLS0gIGRpcmVjdGlvbiBjaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNzYzMjkyICYgUm93TnVtX09HIDw9IDc2MzMxMikgfCAjIDc2MzMwMiAgLS0gIGRpcmVjdGlvbiBjaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTY3OTA5MyAmIFJvd051bV9PRyA8PSAxNjc5MTEzKSB8ICMgMTY3OTEwMyAgLS0gIGRpcmVjdGlvbiBjaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjg2MDkxOCAmIFJvd051bV9PRyA8PSAyODYwOTM4KSAjIDI4NjA5MjggIC0tICBsb29rcyBjb3JyZWN0CiAgICAgICAgICAgKSAlPiUgCiAgICAgICBzZWxlY3QoLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgICAgKQogICAgKQoKClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMpCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBzZWxlY3QoLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykKICAgICAgICAgICAgICApICU+JQogICAgICAgaGVhZCg1MDApCiAgICApCgojIGV4YW1wbGVzIG9mIHRoZSBsYXJnZXN0IFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMgdmFsdWVzLgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTA5MjAwMCAmIFJvd051bV9PRyA8PSAxMDkyMDUwKSB8ICMgMTA5MjAzMCAgLS0gIGRpcmVjdGlvbiBjaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTYwOTQ2MCAmIFJvd051bV9PRyA8PSAxNjA5NDgwKSB8ICMgMTYwOTQ3MCAgLS0gZGlyZWN0aW9uIGNoYW5nZSAKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNTA4OTA0ICYgUm93TnVtX09HIDw9IDUwODkyNCkgfCAjIDUwODkxNCAgLS0gIGRpcmVjdGlvbiBjaGFuZ2UgJiBvcmlnaW5hbCBTdG9wSUQgd2FzIGJhZAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyNDc2MzQ1ICYgUm93TnVtX09HIDw9IDI0NzYzNjUpICMgMjQ3NjM1NSAgLS0gIGRpcmVjdGlvbiBjaGFuZ2UKICAgICAgICAgICApICU+JSAKICAgICAgIHNlbGVjdCgtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbFRpbWVfSHIuCgpWaWV3KFRyYXZEaXN0TWlfUGN0aWxlcyk6IDk4JSBvZiBUcmF2ZWxUaW1lX0hyIGFyZSBiZXR3ZWVuIDcgc2Vjb25kcyBhbmQgNDY0IHNlY29uZHMgKH44IG1pbnV0ZXMpLgpgYGB7cn0KClRyYXZUaW1lSHJfTnRpbGUgPC0gc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9IcgogICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZSgjIFBjdGlsZSA9IG50aWxlKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxUaW1lX0hyLCAxMDApLAogICAgICAgICAjIE1pblIgPSBtaW5fcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsVGltZV9IciksCiAgICAgICAgIFBjdFIgPSBwZXJjZW50X3JhbmsoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFRyYXZlbFRpbWVfSHIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKIyBzdHIoVHJhdlRpbWVIcl9OdGlsZSkKClRyYXZUaW1lSHJfTnRpbGVfUm93cyA8LSBucm93KFRyYXZUaW1lSHJfTnRpbGUpCgojIFZpZXcodGFpbChUcmF2VGltZUhyX050aWxlLCA1MDApKQoKClRyYXZUaW1lSHJfUGN0aWxlcyA8LSBncm91cF9ieShUcmF2VGltZUhyX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGN0Ul9Sb3VuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5UcmF2VGltZUhyQXRQY3RpbGUgPSBtaW4oVHJhdmVsVGltZV9IciksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBUcmF2VGltZUhyX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpLAogICAgICAgICBNaW5UcmF2VGltZVNlY0F0UGN0aWxlID0gTWluVHJhdlRpbWVIckF0UGN0aWxlICogMzYwMAogICAgICAgICkKCnJtKFRyYXZUaW1lSHJfTnRpbGVfUm93cykKcm0oVHJhdlRpbWVIcl9OdGlsZSkKVmlldyhUcmF2VGltZUhyX1BjdGlsZXMpClRyYXZUaW1lSHJfUGN0aWxlcwoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxUaW1lX0hyLgoKSGlzdG9ncmFtIG9mIFRyYXZlbFRpbWVfU2VjLgpgYGB7cn0KClRyYXZUaW1lX1NlY19IaXN0RGVuIDwtIGdncGxvdChmaWx0ZXIoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShUcmF2ZWxUaW1lX1NlYykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFRyYXZlbFRpbWVfU2VjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAuLmRlbnNpdHkuLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvdXIgPSAiZ3JleTYwIiwgc2l6ZSA9IDAuMikgKwogIGdlb21fbGluZShzdGF0ID0gImRlbnNpdHkiLCBjb2xvdXIgPSAicmVkIikgKwogICMgc3RhdF9iaW4oYmlud2lkdGggPSA1LAogICMgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAjICAgICAgICAgIHNpemUgPSAyLjUsCiAgIyAgICAgICAgICB2anVzdCA9IDEuNSwKICAjICAgICAgICAgIGFlcyhsYWJlbCA9IGZvcm1hdCguLmNvdW50Li4sIGJpZy5tYXJrID0gIiwiKQogICMgICAgICAgICAgICAgKSwKICAjICAgICAgICAgKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDE4MCksIHlsaW0gPSBjKDAsIDAuMDIpCiAgICAgICAgICAgICAgICAgKSArCiAgIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGxhYnModGl0bGUgPSAiVmFyaWF0aW9uIGluIFRyYXZlbCBUaW1lIiwKICAgICAgIHggPSAiVHJhdmVsIFRpbWUgKHNlYykiLAogICAgICAgeSA9ICJEZW5zaXR5IgogICAgICApCgpUcmF2VGltZV9TZWNfSGlzdERlbgoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxUaW1lX1NlYy4KClRyYXZlbFRpbWVfU2VjIHZhbHVlcyBhcmUgTkEuCmBgYHtyfQoKc3VtbWFyeShBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsVGltZV9TZWMpCgoKVmlldyhzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBmaWx0ZXIoaXMubmEoVHJhdmVsVGltZV9TZWMpICYKICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICAjIFRyYXZlbFRpbWUgcHVycG9zZWZ1bGx5IG5vdCBjYWxjdWxhdGVkIGhlcmUKICAgICAgICAgICAgICkKICAgICkKCiMgZXhhbXBsZXMgb2YgVHJhdmVsVGltZV9TZWMgdmFsdWVzIHRoYXQgYXJlIE5BLiBUaGVzZSBhcmUgTkEgYmVjYXVzZSB0aGUgRXZlbnRfVGltZSAmIERlcGFydHVyZV9UaW1lIHJlYWRpbmdzIGFyZSBub3QgYWNjdXJhdGUgKGkuZS4sIHRoZSBwcmV2aW91cyBEZXBhcnR1cmVfVGltZSBpcyBCRUZPUkUgb3IgRVFVQUwgVE8gdGhlIGN1cnJlbnQgRXZlbnRfVGltZSkuClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSA5MDgwOSAmIFJvd051bV9PRyA8PSA5MDgyOSkgfCAjIDkwODE5CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDkwODgxICYgUm93TnVtX09HIDw9IDkwOTAxKSB8ICMgOTA4OTEKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjU5NzA2NiAmIFJvd051bV9PRyA8PSAyNTk3MDg2KSB8ICMgMjU5NzA3NgogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyNjEzMzA1ICYgUm93TnVtX09HIDw9IDI2MTMzMjUpICMgMjYxMzMxNQogICAgICAgICAgICkgJT4lIAogICAgICAgc2VsZWN0KC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikpCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbFRpbWVfU2VjLgoKVHJhdmVsVGltZV9TZWMgdmFsdWVzIGFyZSBleHRyZW1lbHkgc21hbGwuCmBgYHtyfQoKVmlldyhzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBmaWx0ZXIoIWlzLm5hKFRyYXZlbFRpbWVfU2VjKQogICAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKFRyYXZlbFRpbWVfU2VjLAogICAgICAgICAgICAgICBkZXNjKFNwZWVkQXZnX01waF9OZXdIdnJzKQogICAgICAgICAgICAgICkgJT4lCiAgICAgICBoZWFkKDUwMCkKICAgICkKCiMgZXhhbXBsZXMgd2hlcmUgVHJhdmVsVGltZV9TZWMgaXMgc21hbGwgKDEgc2VjKSBhbmQgU3BlZWRBdmdfTXBoX05ld0h2cnMgaXMgbGFyZ2UuClZpZXcoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgICkgJT4lIAogICAgICAgZmlsdGVyKChSb3dOdW1fT0cgPj0gMjIxNzM1MyAmIFJvd051bV9PRyA8PSAyMjE3MzczKSB8ICMgMjIxNzM2MwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMDkwMzIxICYgUm93TnVtX09HIDw9IDMwOTAzNDEpIHwgIyAzMDkwMzMxCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDgwNzY0ICYgUm93TnVtX09HIDw9IDgwNzg0KSB8ICMgODA3NzQKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMzM4NDAgJiBSb3dOdW1fT0cgPD0gMzM4NjApICMgMzM4NTAKICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbFRpbWVfU2VjLgoKVHJhdmVsVGltZV9TZWMgdmFsdWVzIGFyZSBleHRyZW1lbHkgbGFyZ2UuCmBgYHtyfQoKVmlldyhzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBmaWx0ZXIoIWlzLm5hKFRyYXZlbFRpbWVfU2VjKQogICAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsVGltZV9TZWMpLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGhfTmV3SHZycwogICAgICAgICAgICAgICkgJT4lCiAgICAgICBoZWFkKDUwMCkKICAgICkKCiMgZXhhbXBsZXMgd2hlcmUgVHJhdmVsVGltZV9TZWMgaXMgbGFyZ2UgYW5kIFNwZWVkQXZnX01waF9OZXdIdnJzIGlzIHNtYWxsLgpWaWV3KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICApICU+JSAKICAgICAgIGZpbHRlcigoUm93TnVtX09HID49IDEwMDc3MDMgJiBSb3dOdW1fT0cgPD0gMTAwNzcyMykgfCAjIDEwMDc3MTMKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjM3MzU2NCAmIFJvd051bV9PRyA8PSAyMzczNTg0KSB8ICMgMjM3MzU3NAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4NjQzNzkgJiBSb3dOdW1fT0cgPD0gODY0Mzk5KSB8ICMgODY0Mzg5CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDI1NzAwNjAgJiBSb3dOdW1fT0cgPD0gMjU3MDA4MCkgIyAyNTcwMDcwCiAgICAgICAgICAgKQogICAgKQoKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9TZWMuCgpBcmUgbGFyZ2UgVHJhdmVsVGltZV9TZWMgdmFsdWVzIHJlbGF0ZWQgdG8gUm91dGVDaGFuZ2VzPyBMb29rcyBsaWtlbHkuIFdoZW4gdGhlIEJ1cyBpbnZvbHZlcyBhIFJvdXRlICJjaGFuZ2UiLCB0aGVyZSBpcyBhbG1vc3QgdHdpY2UgYXMgbGlrZWx5IHRvIGJlIGEgY2FzZSBvZiBhbiBvdXRsaWVyIFRyYXZlbFRpbWVfU2VjIHZhbHVlIChvbiB0aGUgaGlnaCBzaWRlKS4KYGBge3J9CgpUVExhcmdlUnRlQ2huZyA8LSBzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoVFRfT3V0ID0gZmFjdG9yKGlmZWxzZShUcmF2ZWxUaW1lX1NlYyA+IDQ2NCwgICMgdGhpcyBpcyB0aGUgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk91dGxpZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3JtYWwiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICApCgojIHN0cihUVExhcmdlUnRlQ2huZykKCgpUVExhcmdlUnRlQ2huZ19DbnRzIDwtIGdyb3VwX2J5KFRUTGFyZ2VSdGVDaG5nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJ0ZUNoYW5nZTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfT3V0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoQ250cyA9IG4oKQogICAgICAgICAgICkKClRUTGFyZ2VSdGVDaG5nX1NwcmVhZCA8LSBhcy5kYXRhLmZyYW1lKHNwcmVhZChUVExhcmdlUnRlQ2huZ19DbnRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfT3V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ250cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUKICBzZWxlY3QoLVJ0ZUNoYW5nZTIpCgpyb3cubmFtZXMoVFRMYXJnZVJ0ZUNobmdfU3ByZWFkKSA8LSBjKCJDaGFuZ2UiLCAiU2FtZSIpCiMgc3RyKFRUTGFyZ2VSdGVDaG5nX1NwcmVhZCkKCgojIFdoZW4gdGhlIEJ1cyBpbnZvbHZlcyBhIFJvdXRlICJjaGFuZ2UiLCB0aGVyZSBpcyBhbG1vc3QgdHdpY2UgYXMgbGlrZWx5IHRvIGJlIGEgY2FzZSBvZiBhbiBvdXRsaWVyIFRyYXZlbFRpbWVfU2VjIHZhbHVlLgpUVExhcmdlUnRlQ2huZ19TcHJlYWQKcHJvcC50YWJsZShhcy50YWJsZShhcy5tYXRyaXgoVFRMYXJnZVJ0ZUNobmdfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAxCiAgICAgICAgICApCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChUVExhcmdlUnRlQ2huZ19TcHJlYWQpCiAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIDIKICAgICAgICAgICkKCiMgcm0oVFRMYXJnZVJ0ZUNobmcsIFRUTGFyZ2VSdGVDaG5nX1NwcmVhZCkKICAgICAgICAgCgpWaWV3KGZpbHRlcihUVExhcmdlUnRlQ2huZywKICAgICAgICAgICAgIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgUnRlQ2hhbmdlMiA9PSAiU2FtZSIKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxUaW1lX1NlYyksCiAgICAgICAgICAgICAgIFNwZWVkQXZnX01waF9OZXdIdnJzCiAgICAgICAgICAgICAgKSAlPiUKICAgICAgIGhlYWQoNTAwKQogICAgKQoKCiMgZXhhbXBsZXMgd2hlcmUgVHJhdmVsVGltZV9TZWMgaXMgbGFyZ2UgYW5kIFNwZWVkQXZnX01waF9OZXdIdnJzIGlzIHNtYWxsLgpWaWV3KGZpbHRlcihUVExhcmdlUnRlQ2huZywKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyMjUwMjkwICYgUm93TnVtX09HIDw9IDIyNTAzMTApIHwgIyAyMjUwMzAwCiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4Njc3MTcgJiBSb3dOdW1fT0cgPD0gODY3NzM3KSB8ICMgODY3NzI3CiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4NjQzNzkgJiBSb3dOdW1fT0cgPD0gODY0Mzk5KSB8ICMgODY0Mzg5CiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4MDgzOTUgJiBSb3dOdW1fT0cgPD0gODA4NDE1KSAjIDgwODQwNQogICAgICAgICAgICkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9TZWMuCgpJZiBUcmF2ZWxUaW1lX1NlYyBpcyBiZWxvdyB0aGUgNXRoIHBlcmNlbnRpbGUgZm9yIHRoYXQgU3RhcnRTdG9wX0lELCBvciBpZiBUcmF2ZWxUaW1lX1NlYyBpcyBhYm92ZSB0aGUgOTV0aCBwZXJjZW50aWxlIGZvciB0aGF0IFN0YXJ0U3RvcF9JRCwgIGNvbnNpZGVyIHRoaXMgYW4gb3V0bGllci4gIEluIHRoaXMgY2FzZSwgcmVwbGFjZSB0aGUgdmFsdWUgd2l0aCB0aGUgbWVhbiBmb3IgdGhhdCBTdGFydFN0b3BfSUQgYW5kIEhvdXJHcm91cCAoVFRfU2VjX1NTSEdfTWVhbl9GKSwgb3IgaWYgdGhlcmUgYXJlIG5vdCBlbm91Z2ggdmFsdWVzIGF0IHRoZSBIb3VyR3JvdXAgbGV2ZWwsIHJlcGxhY2UgaXQgd2l0aCB0aGUgbWVhbiBmb3IgdGhhdCBTdGFydFN0b3BfSUQuCmBgYHtyfQoKcm0oVFRMYXJnZVJ0ZUNobmcsIFRUTGFyZ2VSdGVDaG5nX0NudHMsIFRUTGFyZ2VSdGVDaG5nX1NwcmVhZCkKCgpOZXdUcmF2VGltZSA8LSBtdXRhdGUoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX05ldyA9IGlmZWxzZSghaXMubmEoVHJhdmVsVGltZV9TZWMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsVGltZV9TZWMgPCBUVF9TZWNfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiBUVF9TZWNfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsVGltZV9TZWMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsVGltZV9TZWMgPCBUVF9TZWNfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiBUVF9TZWNfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250X0YgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxUaW1lX1NlYyA8IFRUX1NlY19TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA+IFRUX1NlY19TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250ID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbFRpbWVfU2VjIDwgVFRfU2VjX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gVFRfU2VjX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudF9GIDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19DbnQgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUnRlQ2hhbmdlMiA9PSAiQ2hhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkpKSwKICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX05ld19MYWJlbCA9IAogICAgICAgICAgIGZhY3RvcihpZmVsc2UoIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxUaW1lX1NlYyA8IFRUX1NlY19TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiBUVF9TZWNfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU0hHX0NudF9GID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgIlRUX1NlY19TU0hHX01lYW5fRiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsVGltZV9TZWMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbFRpbWVfU2VjIDwgVFRfU2VjX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA+IFRUX1NlY19TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJUVF9TZWNfU1NfTWVhbl9GIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsVGltZV9TZWMgPCBUVF9TZWNfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gVFRfU2VjX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudF9GIDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250ID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgIlRUX1NlY19TU19NZWFuIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsVGltZV9TZWMgPCBUVF9TZWNfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gVFRfU2VjX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19DbnQgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFJ0ZUNoYW5nZTIgPT0gIkNoYW5nZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICJUcmF2ZWxUaW1lX1NlYyIKICAgICAgICAgICAgICAgICAgICAgICAgKSkpKQogICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBUVF9Icl9OZXcgPSBUVF9TZWNfTmV3IC8gKDYwICogNjApCiAgICAgICAgICAgKQoKCmRpbShBbGxEYXlzX05ld1RyYXZlbERpc3QpCmRpbShOZXdUcmF2VGltZSkKcm0oQWxsRGF5c19OZXdUcmF2ZWxEaXN0KQoKc3VtbWFyeShzZWxlY3QoTmV3VHJhdlRpbWUsCiAgICAgICAgICAgLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgKQogICApCgpzdHIoc2VsZWN0KE5ld1RyYXZUaW1lLAogICAgICAgICAgIFRyYXZlbFRpbWVfU2VjLAogICAgICAgICAgIFRUX1NlY19OZXcsCiAgICAgICAgICAgVFRfU2VjX05ld19MYWJlbCwKICAgICAgICAgICBUVF9Icl9OZXcKICAgICAgICAgICkKICAgKQoKCnN1bW1hcnkoc2VsZWN0KE5ld1RyYXZUaW1lLAogICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYywKICAgICAgICAgICAgICAgVFRfU2VjX05ldywKICAgICAgICAgICAgICAgVFRfU2VjX05ld19MYWJlbCwKICAgICAgICAgICAgICAgVFRfSHJfTmV3CiAgICAgICAgICAgICAgKQogICAgICAgKQoKYGBgCgoKVGVzdCBpbnZlc3RpZ2F0aW9uIG9mIGp1c3QgdGhlIFgyIFJvdXRlIChib3ggcGxvdHMpLgpgYGB7cn0KClZpZXcoaGVhZChzZWxlY3QoTmV3VHJhdlRpbWUsCiAgICAgICAgICAgICAgICAgLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgICAgICAgKQogICAgICAgICApCiAgICApCgpYMiA8LSBzZWxlY3QoTmV3VHJhdlRpbWUsCiAgICAgICAgICAgICAtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgICkgJT4lIAogIGZpbHRlcihSb3V0ZSA9PSAiWDIiKQoKc3RyKFgyKQoKVmlldyhoZWFkKGFycmFuZ2UoWDIsCiAgICAgICAgICAgICAgICAgIEJ1c19JRCwKICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZQogICAgICAgICAgICAgICAgICksCiAgICAgICAgICA1MDAKICAgICAgICAgKQogICAgKQoKWDJfQnlTdG9wIDwtIGdyb3VwX2J5KFgyLAogICAgICAgICAgICAgICAgICAgICAgU3RvcElEX0NsZWFuCiAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIGFycmFuZ2UoU3RvcElEX0NsZWFuLAogICAgICAgICAgRXZlbnRfVGltZSkgJT4lIAogIG11dGF0ZShFdmVudF9UaW1lX0wxID0gbGFnKEV2ZW50X1RpbWUpLAogICAgICAgICBUaW1lVG9FdmVudF9TZWMgPSBhcy5udW1lcmljKEV2ZW50X1RpbWUgLSBFdmVudF9UaW1lX0wxKSwKICAgICAgICAgVGltZVRvRXZlbnRfTWluID0gVGltZVRvRXZlbnRfU2VjIC8gNjAKICAgICAgICApCgpWaWV3KGhlYWQoWDJfQnlTdG9wLCA1MDApKQoKCiMgQ291bnRfVmFsdWVzIGlzIG5lZWRlZCB0byBkaXNwbGF5IHRoZSBtZWRpYW5zIG9uIHRoZSBib3ggcGxvdHMKQ291bnRfVmFsdWVzIDwtIGRkcGx5KGFzLmRhdGEuZnJhbWUoWDJfQnlTdG9wKSwKICAgICAgICAgICAgICAgICAgICAgIC4oRXZlbnRfVGltZV9Ickdyb3VwKSwKICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZSwKICAgICAgICAgICAgICAgICAgICAgIFZhbHVlX0NvdW50cyA9IG1lZGlhbihUaW1lVG9FdmVudF9NaW4sIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgICAgICAgICAgKQoKVGltZUJ0d0V2ZW50c19YMl9Cb3hQbG90IDwtIGdncGxvdChzZWxlY3QoYXMuZGF0YS5mcmFtZShYMl9CeVN0b3ApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaW1lVG9FdmVudF9NaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHJHcm91cAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKGZhY3RvcihFdmVudF9UaW1lX0hyR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaW1lVG9FdmVudF9NaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBmYWN0b3IoRXZlbnRfVGltZV9Ickdyb3VwKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXI9InJlZCIsIG5vdGNoPVRSVUUsIG5hLnJtID0gVFJVRSkgKwogIGdlb21fdGV4dChkYXRhID0gQ291bnRfVmFsdWVzLAogICAgICAgICAgICBhZXMoeSA9IFZhbHVlX0NvdW50cywKICAgICAgICAgICAgICAgIGxhYmVsID0gZm9ybWF0KHJvdW5kKFZhbHVlX0NvdW50cywgZGlnaXRzID0gMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuc21hbGwgPSAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNQogICAgICAgICAgICkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1KSkgKwogIGNvb3JkX2NhcnRlc2lhbigjIHhsaW0gPSBjKDAsIDE4MCksCiAgICAgICAgICAgICAgICAgIHlsaW0gPSBjKDAsIDEyMCkKICAgICAgICAgICAgICAgICApICsKICBsYWJzKHRpdGxlID0gIkhvdyBPZnRlbiBhbiBYMiBBcnJpdmVzIGF0IGEgR2l2ZW4gU3RvcCIsCiAgICAgICB4ID0gIkhvdXIgR3JvdXAiLAogICAgICAgeSA9ICJUaW1lIEJldHdlZW4gQnVzc2VzIChtaW4pIgogICAgICApCgpUaW1lQnR3RXZlbnRzX1gyX0JveFBsb3QKCmBgYAoKClRlc3QgaW52ZXN0aWdhdGlvbiBvZiBqdXN0IHRoZSBYMiBSb3V0ZSAodmlvbGluIHBsb3RzKS4KYGBge3J9CgpUaW1lQnR3RXZlbnRzX1gyX1Zpb2xpblBsb3QgPC0gZ2dwbG90KHNlbGVjdChhcy5kYXRhLmZyYW1lKFgyX0J5U3RvcCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRpbWVUb0V2ZW50X01pbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKGZhY3RvcihFdmVudF9UaW1lX0hyR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaW1lVG9FdmVudF9NaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBmYWN0b3IoRXZlbnRfVGltZV9Ickdyb3VwKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICBnZW9tX3Zpb2xpbihkcmF3X3F1YW50aWxlcyA9IGMoMC4yNSwgMC41LCAwLjc1KSwKICAgICAgICAgICAgICB0cmltID0gVFJVRSwKICAgICAgICAgICAgICBzY2FsZSA9ICJjb3VudCIsCiAgICAgICAgICAgICAgbmEucm0gPSBUUlVFLAogICAgICAgICAgICAgIHNob3cubGVnZW5kID0gTkEsCiAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBUUlVFCiAgICAgICAgICAgICApICsKICBnZW9tX3RleHQoZGF0YSA9IENvdW50X1ZhbHVlcywKICAgICAgICAgICAgYWVzKHkgPSBWYWx1ZV9Db3VudHMsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGZvcm1hdChyb3VuZChWYWx1ZV9Db3VudHMsIGRpZ2l0cyA9IDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnNtYWxsID0gMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIHNpemUgPSAyLjUsCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNQogICAgICAgICAgICkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1KSkgKwogIGNvb3JkX2NhcnRlc2lhbigjIHhsaW0gPSBjKDAsIDE4MCksCiAgICAgICAgICAgICAgICAgIHlsaW0gPSBjKDAsIDgwKQogICAgICAgICAgICAgICAgICkgKwogIGxhYnModGl0bGUgPSAiSG93IE9mdGVuIGFuIFgyIEFycml2ZXMgYXQgYSBHaXZlbiBTdG9wIiwKICAgICAgIHggPSAiSG91ciBHcm91cCIsCiAgICAgICB5ID0gIlRpbWUgQmV0d2VlbiBCdXNzZXMgKG1pbikiCiAgICAgICkKClRpbWVCdHdFdmVudHNfWDJfVmlvbGluUGxvdAoKYGBgCgoKSW52ZXN0aWdhdGluZyBUcmF2ZWxUaW1lX1NlYy4KYGBge3J9CgpWaWV3KGZpbHRlcihUVExhcmdlUnRlQ2huZywKICAgICAgICAgICAgIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgUnRlQ2hhbmdlMiA9PSAiU2FtZSIKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxUaW1lX1NlYyksCiAgICAgICAgICAgICAgIFNwZWVkQXZnX01waF9OZXdIdnJzCiAgICAgICAgICAgICAgKSAlPiUKICAgICAgIGhlYWQoNTAwKQogICAgKQoKCiMgZXhhbXBsZXMgd2hlcmUgVHJhdmVsVGltZV9TZWMgaXMgc21hbGwgKDEgc2VjKSBhbmQgU3BlZWRBdmdfTXBoX05ld0h2cnMgaXMgbGFyZ2UuClZpZXcoc2VsZWN0KE5ld1RyYXZUaW1lLAogICAgICAgICAgICAjIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICAgLShURF9NaV9xMjpURF9NaV9TU0hHX0NudF9GKSwKICAgICAgICAgICAgLShUVF9Icl9xMjpUVF9Icl9TU0hHX0NudF9GKQogICAgICAgICAgICkgJT4lIAogICAgICAgZmlsdGVyKChSb3dOdW1fT0cgPj0gMjIxNzM1MyAmIFJvd051bV9PRyA8PSAyMjE3MzczKSB8ICMgMjIxNzM2MwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMDkwMzIxICYgUm93TnVtX09HIDw9IDMwOTAzNDEpIHwgIyAzMDkwMzMxCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDgwNzY0ICYgUm93TnVtX09HIDw9IDgwNzg0KSB8ICMgODA3NzQKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMzM4NDAgJiBSb3dOdW1fT0cgPD0gMzM4NjApICMgMzM4NTAKICAgICAgICAgICApCiAgICApCgoKCgoKCiMgZXhhbXBsZXMgd2hlcmUgVHJhdmVsVGltZV9TZWMgaXMgbGFyZ2UgYW5kIFNwZWVkQXZnX01waF9OZXdIdnJzIGlzIHNtYWxsLgpWaWV3KGZpbHRlcihUVExhcmdlUnRlQ2huZywKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyMjUwMjkwICYgUm93TnVtX09HIDw9IDIyNTAzMTApIHwgIyAyMjUwMzAwCiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4Njc3MTcgJiBSb3dOdW1fT0cgPD0gODY3NzM3KSB8ICMgODY3NzI3CiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4NjQzNzkgJiBSb3dOdW1fT0cgPD0gODY0Mzk5KSB8ICMgODY0Mzg5CiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4MDgzOTUgJiBSb3dOdW1fT0cgPD0gODA4NDE1KSAjIDgwODQwNQogICAgICAgICAgICkKICAgICkKYGBgCgoKCgpgYGB7cn0KCiAgICAgICAgIAogICAgICAgICAKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyB1bnVzdWFsbHkgc21hbGwgKHdpdGggVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIGxhcmdlKS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDEwNDIyMjggJiBSb3dOdW1fT0cgPD0gMTA0MjI0OCkgfCAjIDEwNDIyMzgKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNTM4MTYgJiBSb3dOdW1fT0cgPD0gNTM4MzYpIHwgIyA1MzgyNgogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzNjA1NzEgJiBSb3dOdW1fT0cgPD0gMzYwNTkxKSB8ICMgMzYwNTgxCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDUwMjI3MSAmIFJvd051bV9PRyA8PSA1MDIyOTEpICMgNTAyMjgxIChjYW4ndCBleHBsaWFuIHRoZSB3ZWlyZCBUcmF2ZWxUaW1lX1NlYyBjYWxjdWxhdGlvbiBoZXJlIC0gaXQncyBub3QgZXZlbiBhbiBpbnRlZ2VyISkKICAgICAgICAgICApCiAgICApCgojIHN0aWxsIHRyeWluZyB0byBleHBsYWluIDUwMjI4MS4uLm9uIHRoZSBkYXkgb2YgdGhpcyB3ZWlyZG5lc3MsIHRoZSBidXMgd2FzIG9ubHkgaW4gY2lyY3VsYXRpb24gZm9yIDQtNSBzdG9wcyAofjIwIG1pbnV0ZXMpIG9uIHRoYXQgZGF5IChPY3QgNikKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICBCdXNfSUQgPT0gMjcxMQogICAgICAgICAgICkKICAgICkKCgojIGV4cGxvcmluZyBsYXJnZSB2YWx1ZXMgZm9yIFRyYXZlbFRpbWVfU2VjClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPT0gMzAwCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsVGltZV9TZWMpLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyCiAgICAgICAgICAgICAgKQogICAgKQoKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyB1bnVzdWFsbHkgbGFyZ2UgKHdpdGggVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIHNtYWxsLCBzbyBTcGVlZEF2Z19NcGggdmFsdWVzIGFyZSB2ZXJ5IHNtYWxsKS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDI2Mjc0NTkgJiBSb3dOdW1fT0cgPD0gMjYyNzQ3OSkgfCAjIDI2Mjc0NjkKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjE5MzM0NCAmIFJvd051bV9PRyA8PSAyMTkzMzY0KSB8ICMgMjE5MzM1NAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjQ0MTIzICYgUm93TnVtX09HIDw9IDE2NDQxNDMpIHwgIyAxNjQ0MTMzCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDg2OTYwMCAmIFJvd051bV9PRyA8PSA4Njk2MjApICMgODY5NjEwCiAgICAgICAgICAgKQogICAgKQoKYGBgCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIKClZpZXcoU3BlZWRfUGN0aWxlcyk6IDkwJSBvZiBTcGVlZEF2Z19NcGgyIGFyZSBiZXR3ZWVuIH4zbXBoIGFuZCB+NjZtcGguCmBgYHtyfQoKU3BlZWRfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShBbGxEYXlzX05ld1RyYXZlbERpc3QkU3BlZWRBdmdfTXBoMikgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShBbGxEYXlzX05ld1RyYXZlbERpc3QkU3BlZWRBdmdfTXBoMiwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRTcGVlZEF2Z19NcGgyKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkU3BlZWRBdmdfTXBoMiksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgpjb2xuYW1lcyhTcGVlZF9OdGlsZSlbMV0gPC0gIlNwZWVkQXZnX01waDIiCnN0cihTcGVlZF9OdGlsZSkKClNwZWVkX050aWxlX1Jvd3MgPC0gbnJvdyhTcGVlZF9OdGlsZSkKClZpZXcodGFpbChTcGVlZF9OdGlsZSwgNTAwKSkKCgpTcGVlZF9QY3RpbGVzIDwtIGdyb3VwX2J5KFNwZWVkX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblNwZWVkQXRQY3RpbGUgPSBtaW4oU3BlZWRBdmdfTXBoMiksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBTcGVlZF9OdGlsZV9Sb3dzCiAgKSAlPiUgCiAgbXV0YXRlKEN1bVN1bVBBdFAgPSBjdW1zdW0oUGN0c0F0UGN0aWxlKQogICAgICAgICkKClZpZXcoU3BlZWRfUGN0aWxlcykKCmBgYAoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKRXhwbG9yaW5nIHRoZSByZW1vdmFsIG9mIG91dGxpZXIgVHJhdmVsVGltZV9TZWMgYW5kIFRyYXZlbERpc3RhbmNlX01pLgpgYGB7cn0KCnN1bW1hcnkoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgU3BlZWRBdmdfTXBoLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyCiAgICAgICAgICAgICAgKQogICAgICAgKQoKc3VtbWFyeShzZWxlY3QoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gMC4wMDAxODkzOTM5ICYgIyBsb3dlc3Qgbm9uLXplcm8gcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA8IDEuMDgxMjUwMDAwMCAmICMgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gMTAuMDUwMDAwICYgIyAybmQgcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA8IDI5My4wMDAwMDAgIyA5OHRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgU3BlZWRBdmdfTXBoLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyCiAgICAgICAgICAgICAgKQogICAgICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKSGlzdG9ncmFtIG9mIFNwZWVkQXZnX01waDIuCmBgYHtyfQoKU3BlZWRfSGlzdERlbiA8LSBnZ3Bsb3QoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShTcGVlZEF2Z19NcGgyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNwZWVkQXZnX01waDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gLi5kZW5zaXR5Li4KICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvdXIgPSAiZ3JleTYwIiwgc2l6ZSA9IDAuMikgKwogIGdlb21fbGluZShzdGF0ID0gImRlbnNpdHkiLCBjb2xvdXIgPSAicmVkIikgKwogIHN0YXRfYmluKGJpbndpZHRoID0gNSwKICAgICAgICAgICBnZW9tID0gInRleHQiLAogICAgICAgICAgIHNpemUgPSAyLjUsCiAgICAgICAgICAgdmp1c3QgPSAxLjUsCiAgICAgICAgICAgYWVzKGxhYmVsID0gZm9ybWF0KC4uY291bnQuLiwgYmlnLm1hcmsgPSAiLCIpCiAgICAgICAgICAgICAgKSwKICAgICAgICAgICkgKwogICMgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGZvcm1hdCguLmNvdW50Li4sIGJpZy5tYXJrID0gIiwiKQogICMgICAgICAgICAgICAgICksCiAgIyAgICAgICAgICAgc2l6ZSA9IDMsCiAgIyAgICAgICAgICAgbnVkZ2VfeSA9ICguLmNvdW50Li4gKiAwLjEpCiAgIyAgICAgICAgICApICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgNzApLCB5bGltID0gYygwLCAwLjA0KQogICAgICAgICAgICAgICAgICkgKwogICMgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIlZhcmlhdGlvbiBpbiBUcmF2ZWwgU3BlZWQiLAogICAgICAgeCA9ICJBdmVyYWdlIFNwZWVkIChtcGgpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIKICAgICAgKQoKU3BlZWRfSGlzdERlbgoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKSGlzdG9ncmFtIG9mIFNwZWVkQXZnX01waDIgYWZ0ZXIgcmVtb3Zpbmcgb3V0bGllciBUcmF2ZWxUaW1lX1NlYyBhbmQgVHJhdmVsRGlzdGFuY2VfTWkuCmBgYHtyfQoKVmlldyhUcmF2RGlzdE1pTmV3X1BjdGlsZXMpClZpZXcoVHJhdlRpbWVIcl9QY3RpbGVzKQoKU3BlZWROb091dGxpZXJfSGlzdERlbiA8LSBnZ3Bsb3QoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShTcGVlZEF2Z19NcGgyKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IDAuMDc3ODQxMDA1ICYgIyA1dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbERpc3RhbmNlX01pX05ldyA8IDEuMDgxMjUwMDAwMCAmICMgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gMTIuMTAwMDAwICMgNHRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUcmF2ZWxUaW1lX1NlYyA8IDI5My4wMDAwMDAgIyA5OHRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBTcGVlZEF2Z19NcGgyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IC4uZGVuc2l0eS4uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3VyID0gImdyZXk2MCIsIHNpemUgPSAwLjIpICsKICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgY29sb3VyID0gInJlZCIpICsKICBzdGF0X2JpbihiaW53aWR0aCA9IDUsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMi41LAogICAgICAgICAgIHZqdXN0ID0gMS41LAogICAgICAgICAgIGFlcyhsYWJlbCA9IGZvcm1hdCguLmNvdW50Li4sIGJpZy5tYXJrID0gIiwiKQogICAgICAgICAgICAgICksCiAgICAgICAgICApICsKICAjIGdlb21fdGV4dChhZXMobGFiZWwgPSBmb3JtYXQoLi5jb3VudC4uLCBiaWcubWFyayA9ICIsIikKICAjICAgICAgICAgICAgICApLAogICMgICAgICAgICAgIHNpemUgPSAzLAogICMgICAgICAgICAgIG51ZGdlX3kgPSAoLi5jb3VudC4uICogMC4xKQogICMgICAgICAgICAgKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDcwKSwgeWxpbSA9IGMoMCwgMC4wNCkKICAgICAgICAgICAgICAgICApICsKICAjICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJWYXJpYXRpb24gaW4gVHJhdmVsIFNwZWVkIiwKICAgICAgIHN1YnRpdGxlID0gIihyZW1vdmVkIGxvdyBvdXRsaWVycyBvZiBUcmF2ZWwgRGlzdGFuY2UgYW5kIFRyYXZlbCBUaW1lKSIsCiAgICAgICB4ID0gIkF2ZXJhZ2UgU3BlZWQgKG1waCkiLAogICAgICAgeSA9ICJEZW5zaXR5IgogICAgICApCgpTcGVlZE5vT3V0bGllcl9IaXN0RGVuCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIuCgpOZXcgZGF0YXNldCAoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUpIHdoZW4gcmVtb3Zpbmcgb3V0bGllciBsb3cgdmFsdWVzIG9mIFRyYXZlbERpc3RhbmNlX01pX05ldyBhbmQgVHJhdmVsVGltZV9TZWMuCmBgYHtyfQoKVmlldyhUcmF2RGlzdE1pTmV3X1BjdGlsZXMpClZpZXcoVHJhdlRpbWVIcl9QY3RpbGVzKQoKTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUgPC0gZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IC4wNzc4NDEwMDUgJiAjIDV0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWlfTmV3IDwgMS4wODEyNTAwMDAwICYgIyA5OXRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiAxMi4xMDAwMDAgIyA0dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbFRpbWVfU2VjIDwgMjkzLjAwMDAwMCAjIDk4dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpucm93KEFsbERheXNfTmV3VHJhdmVsRGlzdCkgLSBucm93KE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKQoKc3RyKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKQpzdW1tYXJ5KE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcHBlZEF2Z19NcGgyLgoKVmlldyhTcGVlZF9Ob091dF9QY3RpbGVzKTogIEFwcm94aW1hdGVseSA5MCUgb2YgU3BlZWRBdmdfTXBoMiB2YWx1ZXMgYXJlIGJldHdlZW4gfjRtcGggYW5kIH41Nm1waC4KYGBge3J9CgpTcGVlZF9Ob091dF9OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lJFNwZWVkQXZnX01waDIpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUkU3BlZWRBdmdfTXBoMiwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lJFNwZWVkQXZnX01waDIpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lJFNwZWVkQXZnX01waDIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoU3BlZWRfTm9PdXRfTnRpbGUpWzFdIDwtICJTcGVlZEF2Z19NcGgyIgpzdHIoU3BlZWRfTm9PdXRfTnRpbGUpCgpTcGVlZF9Ob091dF9OdGlsZV9Sb3dzIDwtIG5yb3coU3BlZWRfTm9PdXRfTnRpbGUpCgpWaWV3KHRhaWwoU3BlZWRfTm9PdXRfTnRpbGUsIDUwMCkpCgoKU3BlZWRfTm9PdXRfUGN0aWxlcyA8LSBncm91cF9ieShTcGVlZF9Ob091dF9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5TcGVlZEF0UGN0aWxlID0gbWluKFNwZWVkQXZnX01waDIpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gU3BlZWRfTm9PdXRfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSkKICAgICAgICApCgpWaWV3KFNwZWVkX05vT3V0X1BjdGlsZXMpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwcGVkQXZnX01waDIuCgpFeGxvcmluZyBvZGQvaW1wb3NzaWJsZSB2YWx1ZXMuCmBgYHtyfQoKIyBFeHBsb3Jpbmcgd2hlbiBTcGVlZEF2Z19NcGgyIGlzIE5BICAtLSAgZG9lcyBub3Qgb2NjdXIgYXQgYWxsCm5yb3coZmlsdGVyKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lLAogICAgICAgICAgICBpcy5uYShTcGVlZEF2Z19NcGgyKQogICAgICAgICAgICkKICAgICkKCgojIEV4cGxvcmluZyB3aGVuIFNwZWVkQXZnX01waDIgaXMgemVybyAgLS0gIGRvZXMgbm90IG9jY3VyIGF0IGFsbApucm93KGZpbHRlcihOb091dGxpZXJzX1RyYXZlbERpc3ROVGltZSwKICAgICAgICAgICAgU3BlZWRBdmdfTXBoMiA9PSAwCiAgICAgICAgICAgKQogICAgKQoKCiMgZXhhbXBsZXMgd2hlcmUgU3BlZWRBdmdfTXBoMiA8IDMuMjg0ODc3MApWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIFNwZWVkQXZnX01waDIgPiAwICYKICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyIDwgMy4yODQ4NzcwCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKFNwZWVkQXZnX01waDIpCiAgICApCgojIGV4YW1wbGVzIHdoZXJlIFNwZWVkQXZnX01waDIgPCAzLjI4NDg3NzAKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDQ4NTMzOCAmIFJvd051bV9PRyA8PSA0ODUzNTgpIHwgIyA0ODUzNDggIC0tICBFeHRyZW1lIHRyYXZlbCB0aW1lLCBSb3V0ZSBDaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMzQ2OTUyICYgUm93TnVtX09HIDw9IDM0Njk3MikgfCAjIDM0Njk2MiAgLS0gRXh0cmVtZSB0cmF2ZWwgdGltZSwgUm91dGUgQ2hhbmdlIAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA3MDQ5NCAmIFJvd051bV9PRyA8PSA3MDUxNCkgfCAjIDcwNTA0ICAtLSAgRXh0cmVtZSB0cmF2ZWwgdGltZSwgUm91dGUgQ2hhbmdlCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDIwNTE4NDYgJiBSb3dOdW1fT0cgPD0gMjA1MTg2NikgIyAyMDUxODU2ICAtLSAgRXh0cmVtZSB0cmF2ZWwgdGltZSwgUm91dGUgQ2hhbmdlCiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKTGltaXQgdGhlIGRhdGFzZXQgYmFzZWQgb24gU3BlZWRBdmdfTXBoMi4KYGBge3J9CgpOb091dGxpZXJzU3BlZWQgPC0gZmlsdGVyKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIGJldHdlZW4oU3BlZWRBdmdfTXBoMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQuMDY5MzAwLCAjIDV0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1Ni4wNTY1MSAjOTV0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApCgpucm93KE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKSAtIG5yb3coTm9PdXRsaWVyc1NwZWVkKQoKc3VtbWFyeShOb091dGxpZXJzU3BlZWQpCgpgYGAKCgpUcmF2ZWxUaW1lIG5vdyBsb29rcyBsaWtlIGl0IGhhcyBzb21lIG9kZCB2YWx1ZXMgb24gdGhlIGhpZ2ggZW5kLiAgU28gbGV0J3MgbG9vayBhdCB0aG9zZS4KClZpZXcoVHJhdlRpbWVfTm9PdXRfUGN0aWxlcyk6ICBWaXJ0dWFsbHkgYWxsIHRyaXBzIHNob3VsZCB0YWtlIGxlc3MgdGhhbiA1IG1pbnV0ZXMuIChUaGUgOTl0aCBwZXJjZW50aWxlIG9mIG9mIFRyYXZlbFRpbWUgaXMgYXBwcm94aW1hdGVseSA4IG1pbnV0ZXMuKQpgYGB7cn0KClRyYXZUaW1lX05vT3V0X050aWxlIDwtIGFzLmRhdGEuZnJhbWUoTm9PdXRsaWVyc1NwZWVkJFRyYXZlbFRpbWVfSHIpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoTm9PdXRsaWVyc1NwZWVkJFRyYXZlbFRpbWVfSHIsIDEwMCksCiAgICAgICAgIE1pblIgPSBtaW5fcmFuayhOb091dGxpZXJzU3BlZWQkVHJhdmVsVGltZV9IciksCiAgICAgICAgIFBjdFIgPSBwZXJjZW50X3JhbmsoTm9PdXRsaWVyc1NwZWVkJFRyYXZlbFRpbWVfSHIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApCgpjb2xuYW1lcyhUcmF2VGltZV9Ob091dF9OdGlsZSlbMV0gPC0gIlRyYXZlbFRpbWVfSHIiCnN0cihUcmF2VGltZV9Ob091dF9OdGlsZSkKClRyYXZUaW1lX05vT3V0X050aWxlX1Jvd3MgPC0gbnJvdyhUcmF2VGltZV9Ob091dF9OdGlsZSkKClZpZXcodGFpbChUcmF2VGltZV9Ob091dF9OdGlsZSwgNTAwKSkKCgpUcmF2VGltZV9Ob091dF9QY3RpbGVzIDwtIGdyb3VwX2J5KFRyYXZUaW1lX05vT3V0X050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblRyYXZUaW1lSHJBdFBjdGlsZSA9IG1pbihUcmF2ZWxUaW1lX0hyKSwKICAgIENudHNBdFBjdGlsZSA9IG4oKSwKICAgIFBjdHNBdFBjdGlsZSA9IENudHNBdFBjdGlsZSAvIFRyYXZUaW1lX05vT3V0X050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpLAogICAgICAgICBNaW5UcmF2VGltZVNlY0F0UGN0aWxlID0gTWluVHJhdlRpbWVIckF0UGN0aWxlICogKDYwICogNjApCiAgICAgICAgKQoKVmlldyhUcmF2VGltZV9Ob091dF9QY3RpbGVzKQoKYGBgCgoKSW52ZXN0aWdhdGluZyBvZGQgVHJhdmVsVGltZV9TZWMgdmFsdWVzLgoKVHJpcHMgbG9uZ2VyIHRoYW4gfjggbWludXRlcy4KYGBge3J9CgpWaWV3KGZpbHRlcihOb091dGxpZXJzU3BlZWQsCiAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gNDkxICMgbWluIGF0IHRoZSAxMDB0aCBwZXJjZW50aWxlCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsVGltZV9TZWMpCiAgICAgICAgICAgICAgKQogICAgKQoKIyBleGFtcGxlcyBvZiBUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMgdGhhdCBhcmUgbGFyZ2VzdC4KVmlldyhmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAoUm93TnVtX09HID49IDIwNzE3NTkgJiBSb3dOdW1fT0cgPD0gMjA3MTc3OSkgfCAjIDIwNzE3NjkgIC0tICByZXN1bHRzIGZyb20gYSByb3V0ZSBjaGFuZ2UsIGFuZCBhIDNocisgd2FpdCBiZWZvcmUgdGhlIG5ldyByb3V0ZSBzdGFydHMKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTQ3MzY4NiAmIFJvd051bV9PRyA8PSAxNDczNzA2KSB8ICMgMTQ3MzY5NiAgLS0gIHJlc3VsdHMgZnJvbSBhIHJvdXRlIGNoYW5nZSwgYW5kIGEgM2hyIHdhaXQgYmVmb3JlIHRoZSBuZXcgcm91dGUgc3RhcnRzCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDEyMjI4MjIgJiBSb3dOdW1fT0cgPD0gMTIyMjg0MikgfCAjIDEyMjI4MzIgIC0tICByZXN1bHRzIGZyb20gYSByb3V0ZSBjaGFuZ2UsIGFuZCBhIDNociB3YWl0IGJlZm9yZSB0aGUgbmV3IHJvdXRlIHN0YXJ0cwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMDQ2MDg5ICYgUm93TnVtX09HIDw9IDMwNDYxMDkpICMgMzA0NjA5OSAgLS0gIHJlc3VsdHMgZnJvbSBhIHJvdXRlIGNoYW5nZSwgYW5kIGEgM2hyIHdhaXQgYmVmb3JlIHRoZSBuZXcgcm91dGUgc3RhcnRzCiAgICAgICAgICAgKQogICAgKQoKCiMgZXhhbXBsZXMgb2YgVHJhdmVsVGltZV9TZWMgdmFsdWVzIHRoYXQgYXJlIHRoZSBzbWFsbGVzdCBvZiB0aGUgbGFyZ2UuClZpZXcoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMDQ0Njg5ICYgUm93TnVtX09HIDw9IDMwNDQ3MDkpIHwgIyAzMDQ0Njk5ICAtLSAgcmVzdWx0cyBmcm9tIGEgcm91dGUgY2hhbmdlCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDMwMjIzNTggJiBSb3dOdW1fT0cgPD0gMzAyMjM3OCkgfCAjIDMwMjIzNjggIC0tICByZXN1bHRzIGZyb20gYSByb3V0ZSBjaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjk5MzAxNiAmIFJvd051bV9PRyA8PSAyOTkzMDM2KSB8ICMgMjk5MzAyNiAgLS0gIHJlc3VsdHMgZnJvbSBhIHByZXZpb3VzIHJvdXRlIGNoYW5nZSAoY2hhbmdlIG9jY3VycmVkIGluIGRlbGV0ZWQgcm93KQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyNjgzNzAzICYgUm93TnVtX09HIDw9IDI2ODM3MjMpICMgMjY4MzcxMyAgLS0gIHJlc3VsdHMgZnJvbSBhIHByZXZpb3VzIHJvdXRlIGNoYW5nZSAoY2hhbmdlIG9jY3VycmVkIGluIGRlbGV0ZWQgcm93KQogICAgICAgICAgICkKICAgICkKCmBgYAoKCkxldCdzIGxvb2sgYXQgdGhlIFRyYXZlbFRpbWVfU2VjIHZhbHVlcyBhbmQgcm91dGUgY2hhbmdlcyAoRGlyQ2hhbmdlMikuCgpUaGUgOTl0aCBwZXJjZW50aWxlIG9mIFRyYXZlbFRpbWVfU2VjIGZvciBib3RoLCBhbGwgdHJpcHMsIGFuZCBqdXN0IHRob3NlIHRyaXBzIE5PVCBpbnZvbHZpbmcgcm91dGUgY2hhbmdlcyAoRGlyQ2hhbmdlMiA9ICJTYW1lIiksIGlzIGFwcHJveGltYXRlbHkgNW1pbiAoMzAwIHNlYykuCgpOb3RhIEJlbmU6ICBUaGUgcGVyY2VudGlsZSBjYWxjdWxhdGlvbiBoZXJlIGlzIGRlZmluZWQgc2xpZ2h0bHkgZGlmZmVyZW50IHRoYW4gaW4gbW9zdCBvZiB0aGUgYWJvdmUgYW5hbHlzZXMgKHdoaWNoIGdldCB0aGUgbG93ZXN0IHZhbHVlIGluIHRoZSBiaW4gY3JlYXRlZCBieSAxMDAgbnRpbGVzKS4KYGBge3J9CgpzdW1tYXJ5KHNlbGVjdChOb091dGxpZXJzU3BlZWQsCiAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgKQogICAgICAgKQoKc3VtbWFyeShzZWxlY3QoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgIERpckNoYW5nZTIgPT0gIlNhbWUiCiAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgKQogICAgICAgKQoKc3VtbWFyeShzZWxlY3QoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgIERpckNoYW5nZTIgPT0gIkNoYW5nZSIKICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMKICAgICAgICAgICAgICApCiAgICAgICApCgoKVHJhdlRpbWVTZWNfUXRpbGVzX2RmIDwtIGRhdGEuZnJhbWUoUGN0VmFsdWUgPSBzZXEoMCwgMTAwLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQWxsID0gc2VxKDEsIDEwMSwgMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNhbWUgPSBzZXEoMSwgMTAxLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2hhbmdlID0gc2VxKDEsIDEwMSwgMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpUcmF2VGltZVNlY19RdGlsZXNfZGZbICwgMl0gPC0gcXVhbnRpbGUoc2VsZWN0KE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2JzID0gc2VxKDAsIDEsIDAuMDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKClRyYXZUaW1lU2VjX1F0aWxlc19kZlsgLCAzXSA8LSBxdWFudGlsZShzZWxlY3QoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlMiA9PSAiU2FtZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBzZXEoMCwgMSwgMC4wMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKVHJhdlRpbWVTZWNfUXRpbGVzX2RmWyAsIDRdIDwtIHF1YW50aWxlKHNlbGVjdChmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaXJDaGFuZ2UyID09ICJDaGFuZ2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2JzID0gc2VxKDAsIDEsIDAuMDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKClZpZXcoVHJhdlRpbWVTZWNfUXRpbGVzX2RmKQoKYGBgCgoKTGltaXQgdGhlIGRhdGFzZXQgbm93IGJhc2VkIG9uIFRyYXZlbFRpbWVfU2VjLgpgYGB7cn0KClVwcGVyTGltaXRUcmF2VGltZSA8LSBmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjIDw9IDQ5MSAjIG1pbiBhdCB0aGUgMTAwdGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCm5yb3coTm9PdXRsaWVyc1NwZWVkKSAtIG5yb3coVXBwZXJMaW1pdFRyYXZUaW1lKQoKc3RyKFVwcGVyTGltaXRUcmF2VGltZSkKCnN1bW1hcnkoVXBwZXJMaW1pdFRyYXZUaW1lKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEd2VsbF9UaW1lMiAoaG93IGxvbmcgdGhlIGJ1cyBpcyBhdCBhIHN0b3ApLgoKRGlmZmVyZW5jZXMgYmV0d2VlbiBEd2VsbF9UaW1lIChieSBXTUFUQSkgYW5kIER3ZWxsX1RpbWUyIChieSBtZSkgYXBwZWFyIHRvIGJlIGR1ZSB0byBzd2l0Y2hlcyBpbiBSb3V0ZUFsdC4gV01BVEEgY2FsY3VsYXRlcyBEd2VsbF9UaW1lIGJ5IGFuIHVua25vd24gcHJvY2Vzcy4gVGhlIFdNQVRBIGNhbGN1bGF0aW9uIGlzIGVxdWFsIHRvIG15IGNhbGN1bGF0aW9uLCBleGNlcHQgZm9yIHRoZSByZWNvcmRzIGltbWVkYWl0ZWx5IGJlZm9yZSBhbmQgYWZ0ZXIgYSBSb3V0ZUFsdCBzd2l0Y2ggKERpckNoYW5nZTIpLgpgYGB7cn0KClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIER3ZWxsX1RpbWUgIT0gRHdlbGxfVGltZTIKICAgICAgICAgICApCiAgICApCgoKIyBFeGFtcGxlcyB3aGVyZSB0aGUgRHdlbGxfVGltZSBhbmQgRHdlbGxfVGltZTIgYXJlIGRpZmZlcmVudApWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAoIChSb3dOdW1fT0cgPj0gNjUgJiBSb3dOdW1fT0cgPD0gODUpIHwgIyA3NQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjIgJiBSb3dOdW1fT0cgPD0gMTkyKSB8ICMgMTcyCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDQzMTk1MiAmIFJvd051bV9PRyA8PSA0MzE5NzIpIHwgIyA0MzE5NjIKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNDM0NTk1ICYgUm93TnVtX09HIDw9IDQzNDYxNSkgIyA0MzQ2MDUgIC0tICB0aGlzIHJlY29yZCBpcyBOT1QgYSByb3V0ZSBzd2l0Y2gsIGJ1dCBkb2VzIGhhcyBhIFNlcXVlbmNlIHN3aXRjaCAoTWU6IHNob3VsZCB0aGVyZSByZWFsbHkgYmUgYSByb3V0ZSBzd2l0Y2ggaGVyZT8pCiAgICAgICAgICAgICkKICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIER3ZWxsX1RpbWUyIChob3cgbG9uZyB0aGUgYnVzIGlzIGF0IGEgc3RvcCkuCgpGaXJzdCwgY3JlYXRlIHNvbWUgInJhbmsiIHN0YXRzLgpWaWV3KERUMl9QY3RpbGVzKTogOTUlIG9mIER3ZWxsX1RpbWUycyBhcmUgPD0gMjMgc2Vjb25kcy4uLmJ1dCBzb21lIHdlaXJkIChlLmcuLCBuZWFybHkgMiBob3VyIER3ZWxsX1RpbWUycyBleGlzdCkuCmBgYHtyfQoKRHdlbGxUaW1lMl9OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKEFsbERheXNfTmV3T3JkZXIkRHdlbGxfVGltZTIpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoQWxsRGF5c19OZXdPcmRlciREd2VsbF9UaW1lMiwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKEFsbERheXNfTmV3T3JkZXIkRHdlbGxfVGltZTIpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3T3JkZXIkRHdlbGxfVGltZTIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoRHdlbGxUaW1lMl9OdGlsZSlbMV0gPC0gIkR3ZWxsX1RpbWUyIgpzdHIoRHdlbGxUaW1lMl9OdGlsZSkKCkR3ZWxsVGltZTJfTnRpbGVfUm93cyA8LSBucm93KER3ZWxsVGltZTJfTnRpbGUpCgpWaWV3KHRhaWwoRHdlbGxUaW1lMl9OdGlsZSwgNTAwKSkKCgpEd2VsbFRpbWUyX1BjdGlsZXMgPC0gZ3JvdXBfYnkoRHdlbGxUaW1lMl9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgTWluRHdlbGxBdFBjdGlsZSA9IG1pbihEd2VsbF9UaW1lMiksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBEd2VsbFRpbWUyX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpCiAgICAgICAgKQoKVmlldyhEd2VsbFRpbWUyX1BjdGlsZXMpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIER3ZWxsX1RpbWUyIChob3cgbG9uZyB0aGUgYnVzIGlzIGF0IGEgc3RvcCkuCgpIaXN0b2dyYW0gb2YgRHdlbGxfVGltZTIuCmBgYHtyfQoKRHdlbGxUaW1lMl9IaXN0RGVuIDwtIGdncGxvdChBbGxEYXlzX05ld09yZGVyLCBhZXMoeCA9IER3ZWxsX1RpbWUyLCB5ID0gLi5kZW5zaXR5Li4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAiZGVuc2l0eSIsIGNvbG91ciA9ICJyZWQiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDEsIDI1KSwgeWxpbSA9IGMoMCwgMC4wNSkKICAgICAgICAgICAgICAgICApICsKICB4bGFiKCJUaW1lIGEgQnVzIFN0YXlzIGF0IGEgU3RvcCAoc2VjKSIpICsgCiAgeWxhYigiRGVuc2l0eSIpICsgCiAgIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyAKICBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiVmFyaWF0aW9uIGluIEhvdyBMb25nIGEgQnVzIFN0YXlzIGF0IGEgU3RvcCIKICAgICAgICAgICAgICAgICAgICAgICAgICAjICxhdG9wKGl0YWxpYygieHh4eHgiKSwiIikKICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICkKCkR3ZWxsVGltZTJfSGlzdERlbgoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEd2VsbF9UaW1lMiAoaG93IGxvbmcgdGhlIGJ1cyBpcyBhdCBhIHN0b3ApLgoKTG9va2luZyBhdCBzb21lIHdlaXJkbHkgbG9uZyBEd2VsbF9UaW1lMiB2YWx1ZXMuCmBgYHtyfQoKVmlldyhhcnJhbmdlKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICBkZXNjKER3ZWxsX1RpbWUyKQogICAgICAgICAgICApCiAgICApCgoKIyBleGFtcGxlcyBvZiBleHRyZW1lbHkgbGFyZ2UgRHdlbGxfVGltZTJzClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjkyNjY5ICYgUm93TnVtX09HIDw9IDI5MjY4OSkgfCAjIDI5MjY3OQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA1MzEwNTcgJiBSb3dOdW1fT0cgPD0gNTMxMDc3KSB8ICMgNTMxMDY3CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDEzODg2MjcgJiBSb3dOdW1fT0cgPD0gMTM4ODY0NykgfCAjIDEzODg2MzcKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTY0NTcxMSAmIFJvd051bV9PRyA8PSAxNjQ1NzMxKSAjIDE2NDU3MjEKICAgICAgICAgICApCiAgICApCgoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgRHdlbGxfVGltZTIgPT0gMAogICAgICAgICAgICkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRGVsdGFfVGltZSAoaG93IGVhcmx5IG9yIGxhdGUgdGhlIGJ1cyBpcykuCgpWaWV3KERUMl9QY3RpbGVzKTogOTQlIG9mIERlbHRhX1RpbWUgdmFsdWVzIGFyZSBiZXR3ZWVuIC0yMzYgc2Vjb25kcyBhbmQgMSwyNTkgc2Vjb25kcy4gUm91Z2hseSA2NiUgb2YgcmVjb3JkcyBhcmUgd2l0aGluIDUgbWluIGxhdGUgYW5kIDUgbWluIGVhcmx5Li4uYnV0IHNvbWUgd2VpcmQgKGUuZy4sIGFsbW9zdCA1MCBtaW51dGUgbGF0ZSBvciA0MCBtaW51dGUgZWFybHkpIERlbHRhX1RpbWVzIGV4aXN0LgoKTm90ZSB0aGF0IERlbHRhX1RpbWUgaXMgdGhlIGRpZmZlcmVuY2UgZnJvbSB0aGUgc2NoZWR1bGVkIGJ1cyBhcnJpdmFsLiBTbyBpZiB0d28gYnVzZXMgYXJlIHNjaGVkdWxlZCB0byBhcnJpdmUgYXQgYSBkZXN0aW5hdGlvbiBhdCAxMDowMHBtIGFuZCAxMDoyMHBtLCBhbmQgaWYgdGhlIDEwOjIwcG0gYnVzIGhhcyBhIERlbHRhX1RpbWUgb2YgNSBtaW51dGVzLCB0aGVyZSBhcmUgMjUgbWludXRlcyBiZXR3ZWVuIGJ1cyBhcnJpdmFscyBhdCB0aGUgc3RvcC4KCkFsc28gbm90ZSB0aGF0IGJhc2VkIG9uIGEgY29tbWVudCBhdCBodHRwczovL3BsYW5pdG1ldHJvLmNvbS8yMDE2LzExLzE2L2RhdGEtZG93bmxvYWQtbWV0cm9idXMtdmVoaWNsZS1sb2NhdGlvbi1kYXRhLywgdGhlIERlbHRhX1RpbWUgdmFsdWVzIGRvbid0IGFwcGVhciB0byBjb2luY2lkZSB3aXRoIHB1Ymxpc2hlZCBidXMgc2NoZWR1bGVzIChlLmcuLCB0aGUgWDIgZGVwYXJ0aW5nIGV2ZXJ5IDggbWludXRlcyBkdXJpbmcgcGVhayBob3VycykuCmBgYHtyfQoKRGVsdFRpbWVfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lLCAxMDApLAogICAgICAgICBNaW5SID0gbWluX3JhbmsoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoRGVsdFRpbWVfTnRpbGUpWzFdIDwtICJEZWx0YV9UaW1lIgpzdHIoRGVsdFRpbWVfTnRpbGUpCgpEZWx0VGltZV9OdGlsZV9Sb3dzIDwtIG5yb3coRGVsdFRpbWVfTnRpbGUpCgpWaWV3KHRhaWwoRGVsdFRpbWVfTnRpbGUsIDUwMCkpCgoKRGVsdFRpbWVfUGN0aWxlcyA8LSBncm91cF9ieShEZWx0VGltZV9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5EZWx0VGltZUF0UGN0aWxlID0gbWluKERlbHRhX1RpbWUpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gRGVsdFRpbWVfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSkKICAgICAgICApCgpWaWV3KERlbHRUaW1lX1BjdGlsZXMpCkRlbHRUaW1lX1BjdGlsZXMKCiMgfjY2JSBvZiByb3dzIGFyZSBiZXR3ZWVuIDUgbWluIGxhdGUgYW5kIDUgbWluIGVhcmx5Cm5yb3coZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIERlbHRhX1RpbWUgPj0gLTMwMCAmCiAgICAgICAgICAgICAgRGVsdGFfVGltZSA8PSAzMDAKICAgICAgICAgICApCiAgICApIC8gbnJvdyhBbGxEYXlzX05ld09yZGVyKQoKCiMgZXhhbXBsZXMgb2Ygd2VpcmQgbGFyZ2UgRGVsdGFfVGltZXMKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgRGVsdGFfVGltZSA8IC00MjAyIHwKICAgICAgICAgICAgICBEZWx0YV9UaW1lID4gMTcwNQogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShkZXNjKERlbHRhX1RpbWUpCiAgICAgICAgICAgICAgKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEZWx0YV9UaW1lIChob3cgZWFybHkgb3IgbGF0ZSB0aGUgYnVzIGlzKS4KCkRlbHRhX1RpbWUgaGlzdG9ncmFtLgpgYGB7cn0KCkRlbHRUaW1lX0hpc3REZW4gPC0gZ2dwbG90KEFsbERheXNfTmV3T3JkZXIsIGFlcyh4ID0gKERlbHRhX1RpbWUgLyA2MCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gLi5kZW5zaXR5Li4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gKDUvNjApLCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAiZGVuc2l0eSIsIGNvbG91ciA9ICJyZWQiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKC01LCA1KSkgKwogIHhsYWIoIkJ1cyBMYXRlbmVzcyAobWluKSIpICsgCiAgeWxhYigiRGVuc2l0eSIpICsgCiAgIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyAKICBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiVmFyaWF0aW9uIGluIEhvdyBFYXJseS9MYXRlIGEgQnVzIElzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBhdG9wKGl0YWxpYygiKHBvc2l0aXZlIHZhbHVlcyBhcmUgbGF0ZSBhcnJpdmFscykiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICkKCkRlbHRUaW1lX0hpc3REZW4KCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRGVsdGFfVGltZSAoaG93IGVhcmx5IG9yIGxhdGUgdGhlIGJ1cyBpcykuCgpEZWx0YV9UaW1lIGJveHBsb3QuCmBgYHtyfQoKIyBDb3VudF9WYWx1ZXMgaXMgbmVlZGVkIHRvIGRpc3BsYXkgdGhlIG1lZGlhbnMgb24gdGhlIGJveCBwbG90cwpDb3VudF9WYWx1ZXMgPC0gZGRwbHkoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgIC4oRXZlbnRfVGltZV9Ickdyb3VwKSwKICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZSwKICAgICAgICAgICAgICAgICAgICAgIFZhbHVlX0NvdW50cyA9IG1lZGlhbihEZWx0YV9UaW1lIC8gNjAsIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgICAgICAgICAgKQoKRGVsdFRpbWVfQm94UGxvdCA8LSBnZ3Bsb3QoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKGZhY3RvcihFdmVudF9UaW1lX0hyR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVsdGFfVGltZSAvIDYwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGZhY3RvcihFdmVudF9UaW1lX0hyR3JvdXApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJyZWQiLCBub3RjaD1UUlVFKSArIAogICMgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zMDAsIDEyMDApKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC01LCAyMCkpICsKICBnZW9tX3RleHQoZGF0YSA9IENvdW50X1ZhbHVlcywKICAgICAgICAgICAgYWVzKHkgPSBWYWx1ZV9Db3VudHMsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGZvcm1hdChyb3VuZChWYWx1ZV9Db3VudHMsIGRpZ2l0cyA9IDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnNtYWxsID0gMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICB2anVzdCA9IC0wLjUKICAgICAgICAgICApICsKICB4bGFiKCJIb3VyIEdyb3VwIikgKyAKICB5bGFiKCJCdXMgTGF0ZW5lc3MgKG1pbnV0ZXMpIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSkpICsgCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiLCBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiSG93IEVhcmx5L0xhdGUgaXMgdGhlIEJ1cyAoYnkgSG91ciBHcm91cCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGF0b3AoaXRhbGljKCIocG9zaXRpdmUgdmFsdWVzIGFyZSBsYXRlIGFycml2YWxzKSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgKQoKRGVsdFRpbWVfQm94UGxvdAoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEZWx0YV9UaW1lIChob3cgZWFybHkgb3IgbGF0ZSB0aGUgYnVzIGlzKS4KCkV4cGxvcmluZyAiZXh0cmVtZSIgRGVsdGFfVGltZXMuICBGaXJzdCBsZXQncyBnZXQgc29tZSAicmFuayIgc3RhdHMuCmBgYHtyfQoKVmlldyhEZWx0VGltZV9QY3RpbGVzKQpEZWx0VGltZV9QY3RpbGVzCgoKRGVsdFRpbWVBYnNfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShhYnMoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSkgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShhYnMoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKGFicyhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhhYnMoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgpjb2xuYW1lcyhEZWx0VGltZUFic19OdGlsZSlbMV0gPC0gIkRlbHRhX1RpbWVfQWJzIgpzdHIoRGVsdFRpbWVBYnNfTnRpbGUpCgpEZWx0VGltZUFic19OdGlsZV9Sb3dzIDwtIG5yb3coRGVsdFRpbWVBYnNfTnRpbGUpCgpWaWV3KHRhaWwoRGVsdFRpbWVBYnNfTnRpbGUsIDUwMCkpCgoKRGVsdFRpbWVBYnNfUGN0aWxlcyA8LSBncm91cF9ieShEZWx0VGltZUFic19OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5EZWx0VGltZUF0UGN0aWxlID0gbWluKERlbHRhX1RpbWVfQWJzKSwKICAgIENudHNBdFBjdGlsZSA9IG4oKSwKICAgIFBjdHNBdFBjdGlsZSA9IENudHNBdFBjdGlsZSAvIERlbHRUaW1lX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpCiAgICAgICAgKQoKVmlldyhEZWx0VGltZUFic19QY3RpbGVzKQpEZWx0VGltZUFic19QY3RpbGVzCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIERlbHRhX1RpbWUgKGhvdyBlYXJseSBvciBsYXRlIHRoZSBidXMgaXMpLgoKRXhwbG9yaW5nICJleHRyZW1lIiBEZWx0YV9UaW1lcy4gIFRoZW4gbGV0J3MgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mIGJ1c2VzIHRoYXQgYXJlIDEwIG1pbnV0ZXMgKG9yIG1vcmUpIGxhdGUvZWFybHkuCmBgYHtyfQoKSHJHcm91cF9EZWx0YVRpbWVfQWxsIDwtIGdyb3VwX2J5KEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKEV2ZW50QWxsX0NudCA9IG4oKQogICAgICAgICAgICkKCnN0cihIckdyb3VwX0RlbHRhVGltZV9BbGwpClZpZXcoSHJHcm91cF9EZWx0YVRpbWVfQWxsKQoKCkhyR3JvdXBfRGVsdGFUaW1lX0Fib3ZlMTBNaW4gPC0gZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFicyhEZWx0YV9UaW1lKSA+PSA2MDAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBncm91cF9ieShFdmVudF9UaW1lX0hyR3JvdXApICU+JSAKICBzdW1tYXJpc2UoRXZlbnRBYm92ZTEwX0NudCA9IG4oKQogICAgICAgICAgICkKCnN0cihIckdyb3VwX0RlbHRhVGltZV9BYm92ZTEwTWluKQpWaWV3KEhyR3JvdXBfRGVsdGFUaW1lX0Fib3ZlMTBNaW4pCgoKSHJHcm91cF9EZWx0YVRpbWVDb21wYXJlIDwtIGlubmVyX2pvaW4oSHJHcm91cF9EZWx0YVRpbWVfQWJvdmUxME1pbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSHJHcm91cF9EZWx0YVRpbWVfQWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIkV2ZW50X1RpbWVfSHJHcm91cCIgPSAiRXZlbnRfVGltZV9Ickdyb3VwIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoUGN0RXZlbnRzQWJvdmUxMCA9IEV2ZW50QWJvdmUxMF9DbnQgLyBFdmVudEFsbF9DbnQpCgpWaWV3KEhyR3JvdXBfRGVsdGFUaW1lQ29tcGFyZSkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRGVsdGFfVGltZSAoaG93IGVhcmx5IG9yIGxhdGUgdGhlIGJ1cyBpcykuCgpRdWlja2x5IHBsb3QgdGhlc2UgImV4dHJlbWUiIERlbHRhX1RpbWVzLiAKYGBge3J9CgpEZWx0VGltZV9BYm92ZTEwX0NvbHMgPC0gZ2dwbG90KEhyR3JvdXBfRGVsdGFUaW1lQ29tcGFyZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoZmFjdG9yKEV2ZW50X1RpbWVfSHJHcm91cCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdEV2ZW50c0Fib3ZlMTAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX2NvbChmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGZvcm1hdChyb3VuZChQY3RFdmVudHNBYm92ZTEwLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5zbWFsbCA9IDIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICApLAogICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgbnVkZ2VfeSA9IChIckdyb3VwX0RlbHRhVGltZUNvbXBhcmUkUGN0RXZlbnRzQWJvdmUxMCAqIC0wLjEpCiAgICAgICAgICAgKSArCiAgIyBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTUsIDUpKSArCiAgeGxhYigiSG91ciBHcm91cCIpICsgCiAgeWxhYigiUGVyY2VudCBvZiBBbGwgQnVzIEFycml2YWxzIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1KSkgKwogIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJXaGVuIGlzIGEgQnVzIDEwKyBNaW51dGVzIExhdGUvRWFybHkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAsYXRvcChpdGFsaWMoInBvc2l0aXZlIHZhbHVlcyBhcmUgbGF0ZSBhcnJpdmFscyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAiIgogICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICkKCkRlbHRUaW1lX0Fib3ZlMTBfQ29scwoKYGBgCgoKUXVpY2sgaW52ZXN0aWdhdGlvbiBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRHdlbGxfVGltZTIgKHRoZSB0aW1lIGEgYnVzIGlzIGF0IGEgc3RvcCkgYW5kIERlbHRhX1RpbWUgKGhvdyBlYXJseS9sYXRlIHRoZSBidXMgaXMpLgoKQ29ycmVsYXRpb24uCmBgYHtyfQoKRHdlbGxURGVsdGFUX0NvcnIgPC0gYXMubWF0cml4KGNvcih4ID0gQWxsRGF5c19OZXdPcmRlciREd2VsbF9UaW1lMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZSA9ICJwYWlyd2lzZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCkR3ZWxsVERlbHRhVF9Db3JyCgpgYGAKCgpRdWljayBpbnZlc3RpZ2F0aW9uIG9uIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBEd2VsbF9UaW1lMiAodGhlIHRpbWUgYSBidXMgaXMgYXQgYSBzdG9wKSBhbmQgRGVsdGFfVGltZSAoaG93IGVhcmx5L2xhdGUgdGhlIGJ1cyBpcykuCgpOZXh0LCBsZXQncyBnZXQgYSBzYW1wbGUgb2YgZGF0YSBmb3IgcGxvdHRpbmcuIExldCdzIGRvIHRoaXMgZm9yIHRoZSBmdWxsIGRhdGFzZXQgKEFsbERheXNfTmV3T3JkZXIpLgpgYGB7cn0KCkFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wIDwtIHNhbXBsZV9mcmFjKEFsbERheXNfTmV3T3JkZXIsIDAuMSkgJT4lIAogIHNlbGVjdChEZWx0YV9UaW1lLAogICAgICAgICBEd2VsbF9UaW1lMgogICAgICAgICkgJT4lIAogIG11dGF0ZShEYXRhU2V0ID0gIkFsbERhdGEiKQoKc3RyKEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wKQoKYGBgCgoKUXVpY2sgaW52ZXN0aWdhdGlvbiBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRHdlbGxfVGltZTIgKHRoZSB0aW1lIGEgYnVzIGlzIGF0IGEgc3RvcCkgYW5kIERlbHRhX1RpbWUgKGhvdyBlYXJseS9sYXRlIHRoZSBidXMgaXMpLgoKTGV0J3MgYWxzbyBnZXQgYSBzYW1wbGUgb2YgZGF0YSBmb3IgcGxvdHRpbmcsIGJ1dCB3aXRoIGEgZGF0c2V0IHRoYXQgcmVtb3ZlcyBvdXRsaWVycy4KYGBge3J9CgpWaWV3KERlbHRUaW1lX1BjdGlsZXMpClZpZXcoRHdlbGxUaW1lMl9QY3RpbGVzKQoKQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCA8LSBmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV0d2VlbihEZWx0YV9UaW1lLCAtNDAyLCAxNzA1KSAmICMgcmVtb3ZlcyBhYm91dCAyJSBvZiBEZWx0YV9UaW1lIHZhbHVlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJldHdlZW4oRHdlbGxfVGltZTIsIDEsIDYzKSAgIyByZW1vdmVzIGFib3V0IDIlIG9mIER3ZWxsX1RpbWUyIHZhbHVlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHNhbXBsZV9mcmFjKDAuMSkgJT4lIAogIHNlbGVjdChEZWx0YV9UaW1lLAogICAgICAgICBEd2VsbF9UaW1lMgogICAgICAgICkgJT4lIAogIG11dGF0ZShEYXRhU2V0ID0gIk91dGxpZXJzUmVtb3ZlZCIpCgpzdHIoQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCkKCmBgYAoKClF1aWNrIGludmVzdGlnYXRpb24gb24gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIER3ZWxsX1RpbWUyICh0aGUgdGltZSBhIGJ1cyBpcyBhdCBhIHN0b3ApIGFuZCBEZWx0YV9UaW1lIChob3cgZWFybHkvbGF0ZSB0aGUgYnVzIGlzKS4KClBsb3R0aW5nIHRoZSBkYXRhIGZyb20gdGhlIGRhdGFzZXQgdGhhdCBkb2VzIG5vdCByZW1vdmUgb3V0bGllcnMuCmBgYHtyfQoKRHdlbGxURGVsdGFUX1NjYXR0ZXIgPC0gZ2dwbG90KEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKER3ZWxsX1RpbWUyLCBEZWx0YV9UaW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9zaGFwZShzb2xpZCA9IEZBTFNFKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gInJlZCIpICsKICAjIHhsYWIoIlRpbWUgYXQgU3RvcCAoc2VjKSIpICsgCiAgIyB5bGFiKCJMYXRlbmVzcyAoc2VjKSIpICsKICBhbm5vdGF0ZShsYWJlbCA9IGxtX2VxbihkZiA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBBbGxEYXlzX05ld09yZGVyXzEwUGN0U2FtcCREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBBbGxEYXlzX05ld09yZGVyXzEwUGN0U2FtcCREd2VsbF9UaW1lMgogICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICB4ID0gMjIwMCwKICAgICAgICAgICB5ID0gNjAwLAogICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgY29sb3VyID0gInJlZCIsCiAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICBsYWJzKHRpdGxlID0gIkxhdGVuZXNzIHZzIFRpbWUgYXQgU3RvcCIsCiAgICAgICBzdWJ0aXRsZSA9ICIobm8gb3V0bGllcnMgcmVtb3ZlZCkiLAogICAgICAgeCA9ICJUaW1lIGF0IFN0b3AgKHNlYykiLAogICAgICAgeSA9ICJMYXRlbmVzcyAoc2VjKSIKICAgICAgKQogICMgZ2d0aXRsZShleHByZXNzaW9uKGF0b3AoIkxhdGVuZXNzIHZzIFRpbWUgYXQgU3RvcCIKICAjICAgICAgICAgICAgICAgICAgICAgICAgICxhdG9wKGl0YWxpYygiKG5vIG91dGxpZXJzIHJlbW92ZWQpIiksCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIgogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICkKICAjICAgICAgICAgICAgICAgICAgICkKICAjICAgICAgICApCiMgKwojICAgZ2VvbV9qaXR0ZXIoKQoKRHdlbGxURGVsdGFUX1NjYXR0ZXIKCmBgYAoKClF1aWNrIGludmVzdGlnYXRpb24gb24gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIER3ZWxsX1RpbWUyICh0aGUgdGltZSBhIGJ1cyBpcyBhdCBhIHN0b3ApIGFuZCBEZWx0YV9UaW1lIChob3cgZWFybHkvbGF0ZSB0aGUgYnVzIGlzKS4KClBsb3R0aW5nIHRoZSBkYXRhIGZyb20gdGhlIGRhdGFzZXQgdGhhdCBkb2VzIHJlbW92ZSBvdXRsaWVycy4KYGBge3J9CgpEd2VsbFREZWx0YVRfU2NhdHRlcl9Ob0V4dHJlbWVzIDwtIGdncGxvdChBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoRHdlbGxfVGltZTIsIERlbHRhX1RpbWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEsIGFscGhhID0gMC41KSArCiAgc2NhbGVfc2hhcGUoc29saWQgPSBGQUxTRSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9ICJibHVlIikgKwogICMgeGxhYigiVGltZSBhdCBTdG9wIChzZWMpIikgKyAKICAjIHlsYWIoIkxhdGVuZXNzIChzZWMpIikgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wJER3ZWxsX1RpbWUyCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIHggPSA1MCwKICAgICAgICAgICB5ID0gLTQ3NSwKICAgICAgICAgICBnZW9tID0gInRleHQiLAogICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgIGNvbG91ciA9ICJibHVlIiwKICAgICAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgICAgICkgKwogIGxhYnModGl0bGUgPSAiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIiwKICAgICAgIHN1YnRpdGxlID0gIigyJSBvZiBvdXRsaWVycyByZW1vdmVkKSIsCiAgICAgICB4ID0gIlRpbWUgYXQgU3RvcCAoc2VjKSIsCiAgICAgICB5ID0gIkxhdGVuZXNzIChzZWMpIgogICAgICApCiAgIyBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIgogICMgICAgICAgICAgICAgICAgICAgICAgICAgLGF0b3AoaXRhbGljKCIoMiUgb2Ygb3V0bGllcnMgcmVtb3ZlZCkiKSwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAjICAgICAgICAgICAgICAgICAgICAgICAgKQogICMgICAgICAgICAgICAgICAgICAgKQogICMgICAgICAgICkKIyArCiMgICBnZW9tX2ppdHRlcigpCgpEd2VsbFREZWx0YVRfU2NhdHRlcl9Ob0V4dHJlbWVzCgpgYGAKCgpRdWljayBpbnZlc3RpZ2F0aW9uIG9uIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBEd2VsbF9UaW1lMiAodGhlIHRpbWUgYSBidXMgaXMgYXQgYSBzdG9wKSBhbmQgRGVsdGFfVGltZSAoaG93IGVhcmx5L2xhdGUgdGhlIGJ1cyBpcykuCgpQbG90dGluZyB0aGUgZGF0YSBmcm9tIGJvdGggZGF0YXNldHMgdG9nZXRoZXIuCmBgYHtyfQoKQ29tYmluZWREYXRhIDwtIHJiaW5kKEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcAogICAgICAgICAgICAgICAgICAgICApCgpDb21iaW5lZERhdGEkRGF0YVNldCA8LSBmYWN0b3IoQ29tYmluZWREYXRhJERhdGFTZXQpCgpzdHIoQ29tYmluZWREYXRhKQoKCkR3ZWxsVERlbHRhVF9TY2F0dGVyX0NvbWJpbmVkIDwtIGdncGxvdChDb21iaW5lZERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IER3ZWxsX1RpbWUyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBEZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IERhdGFTZXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEsIGFscGhhID0gMC41KSArCiAgc2NhbGVfc2hhcGUoc29saWQgPSBGQUxTRSkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCA1MDApLCB5bGltID0gYygtMTAwMCwgMjAwMCkKICAgICAgICAgICAgICAgICApICsKICBnZW9tX3Ntb290aChkYXRhID0gZmlsdGVyKENvbWJpbmVkRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIERhdGFTZXQgPT0gIkFsbERhdGEiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwKICAgICAgICAgICAgICBjb2xvdXIgPSAicmVkIgogICAgICAgICAgICAgKSArCiAgZ2VvbV9zbW9vdGgoZGF0YSA9IGZpbHRlcihDb21iaW5lZERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRhU2V0ID09ICJPdXRsaWVyc1JlbW92ZWQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwKICAgICAgICAgICAgICBjb2xvdXIgPSAiYmx1ZSIKICAgICAgICAgICAgICkgKwogICMgZmFjZXRfd3JhcCggfiBEYXRhU2V0LCBuY29sID0gMikgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wJERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wJER3ZWxsX1RpbWUyCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIHggPSAzMDAsCiAgICAgICAgICAgeSA9IC02MDAsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAicmVkIiwKICAgICAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgICAgICkgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wJER3ZWxsX1RpbWUyCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIHggPSAzMDAsCiAgICAgICAgICAgeSA9IC04MDAsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAiYmx1ZSIsCiAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGxhYnModGl0bGUgPSAiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIiwKICAgICAgIHggPSAiVGltZSBhdCBTdG9wIChzZWMpIiwKICAgICAgIHkgPSAiTGF0ZW5lc3MgKHNlYykiCiAgICAgICkKICAjIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJMYXRlbmVzcyB2cyBUaW1lIGF0IFN0b3AiCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAsYXRvcChpdGFsaWMoIjIlIG9mIG91dGxpZXJzIHJlbW92ZWQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgICIiCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICkKICAgICAgICAgIyAgICAgICAgICAgICAgICAgKQogICAgICAgICAjICAgICAgICAgICAgKQogICAgICAgICAjICkKIyArCiMgICBnZW9tX2ppdHRlcigpCgpEd2VsbFREZWx0YVRfU2NhdHRlcl9Db21iaW5lZAoKYGBgCgoKCgoKCgoKCgoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgo=